Skip to content

Proposal for sessions/bundles with a start/stop API and simple example#481

Closed
davidozog wants to merge 2 commits into
openshmem-org:masterfrom
davidozog:wip/bundles
Closed

Proposal for sessions/bundles with a start/stop API and simple example#481
davidozog wants to merge 2 commits into
openshmem-org:masterfrom
davidozog:wip/bundles

Conversation

@davidozog

Copy link
Copy Markdown
Collaborator

This PR addresses issue #189.

As always I appreciate feedback, thanks!

Comment thread content/bundles_intro.tex
@@ -0,0 +1,23 @@
\newtext{The performance of \openshmem programs that issue many consecutive and

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Irrespective of small/large-sized messages - bundles/sessions provides hints to the implementation to optimize. We need a better definition of what a bundle or session refers to.

Copy link
Copy Markdown
Collaborator Author

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, but I don't want to be prescriptive with defining the optimization... Do you have any suggestions on wording?

\begin{apidefinition}

\begin{Csynopsis}
void @\FuncDecl{shmem\_bundle\_start}@(void);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

why do we need a separate API - I don't see why someone can't use the super-set API with ctx.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I don't think we need it, but I included for consistency with fence, quiet, PE-specific quiet, and the RMAs/AMOs. It's just a convenience routine - I'm happy to remove if a majority find it unnecessary.

\end{apiarguments}

\apidescription{
The \FUNC{shmem\_bundle\_stop} routine provides a hint to the \openshmem

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We are not defining the exit condition for this routine correctly - I'm not sure whether the intention is to have an implicit quiet as part of this routine.
Based on the example - it looks like there is an implicit quiet. Not sure - why this is defined in such a way.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

As discussed in the WG's, there is no implicit quiet at the end of a bundle (but there is within the shmem_free, right? I don't think the example needs a quiet, but maybe the example could be improved in this regard).

My intent was for the statement:

[bundling routines] do not affect the completion or ordering semantics of any OpenSHMEM
routines in the program

to cover this. But perhaps it would help to include something like this in the API description or a note?


\begin{Csynopsis}
void @\FuncDecl{shmem\_bundle\_start}@(void);
void @\FuncDecl{shmem\_ctx\_bundle\_start}@(shmem_ctx_t ctx);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think - we are missing two things:

  1. There should a hint parameter for this routine - apart from the context. Hints should help implementations to support different options.
  2. Should there be shmem_team_t as part of the argument? I'm not entirely sure about this requirement. My initial thinking is we should support - I'm open to suggestions. Adding teams argument - doesn't make it a collective call. Though, we can also retrieve this information from the ctx argument - it is useful to have teams argument along with or instead of teams. Proposed API:
vous shmem_bundle_start(shmem_team_t team, shmem_ctx_t ctx, int hints)

Hint can be used to determine whether team or ctx is passed. If multiple CTX or all CTX from a team is expected to create separate bundles - it would be optimal to use a single internal bundle.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I'm confused on this one - doesn't the context directly imply a team? I don't see why we would allow bundling on a team other than the context it's associated with...?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Assume the users want to create bundles for separate shared contexts from the same team. With this API, they would have calling bundle_start separately on each context. Internally, we couldn't perform chaining correctly - with just this information. As the network resource might be shared by multiple other shared contexts in that team.

My attempt to solve this - just pass team and say all contexts in this team is expected to be bundled. With this information and internal network resource information - implementations can create separate or one single chain.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nevertheless - we need hints argument irrespective of whether we plan to add team argument or not.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

hint would say - SHMEM_BUNDLE_TEAM or SHMEM_BUNDLE_CTX

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

+1 to the hints suggestion. It's long options on context creation.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think we should have hints inside this routine and not in the context - I don't think we want to restrict the users to use a separate context for these sort of optimizations. They should be able to use the same context within the session and outside the session

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

If they misuse them - say use a shared context within session and simulateously outside on another thread - it is their perf issue to handle.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I agree. Sorry, my comment was a bit confusing. I was suggesting that the parameter to the proposed function could be called long options if we want to follow the convention set by the contexts API.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Hah! I like the long options suggestion as well, but I'm still confused about the team...

If multiple contexts share an underlying HW resource (STX or whatever) then yes, the runtime may choose to bundle across those contexts, but how does passing the team help? The runtime could check if the context is shared, and it should know what team it's on, and what other contexts are shared on that team. Am I missing something?

\apidescription{
The \FUNC{shmem\_bundle\_stop} routine provides a hint to the \openshmem
library to stop applying bundling-related optimizations.
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We are not specifically making it mandatory for users to call a stop after a start is called. I think, we should make it mandatory to call a stop after a start.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Agreed - thanks.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

And some advice that it's a bad idea to go into non-shmem code (like a long computation loop) without a stop?

\apidescription{
The \FUNC{shmem\_bundle\_start} routine provides a hint to the \openshmem
library to being applying bundling-related optimizations.
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Do we need to handle a scenario - when multiple starts are called recursively without breaking the bundle?

shmem_start_bundle(ctx1)
shmem_start_bundle(ctx1)
shmem_start_bundle(ctx1)
shmem_stop_bundle(ctx1)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Good catch - my hunch is to disallow this. Do you think so?

It might make sense to allow nesting across different contexts, do you think that should be allowed?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I'm not fond of nesting or disallowing. Just a note that stop affects them all in that example?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Something like "If bundling is already started, a call to shmem_start_bundle has no effect and if it is stopped, a call to shmem_stop_bundle has no effect."?

@naveen-rn

Copy link
Copy Markdown
Contributor

One-more item from #189 are not yet addressed:

  1. Defining the relationship between memory ordering routines and bundle? What happens when a memory ordering (explicit or implicit from collectives) is called within a bundle

@davidozog

Copy link
Copy Markdown
Collaborator Author

Thanks very much for the review @naveen-rn.

  1. Defining the relationship between memory ordering routines and bundle? What happens when a memory ordering (explicit or implicit from collectives) is called within a bundle

I tried to capture that with:

[bundling routines] do not affect the completion or ordering semantics of any OpenSHMEM routines in the program.

For example, if a quiet occurs within a bundle, then the runtime must ensure remote completions on the calling PE as normal. Also:

routines, such as ... the memory ordering routines might require the library to enforce remote completion, reducing the potential benefit of bundling optimizations.

So while it's not strictly prohibited in this draft, it is discouraged to include memory ordering within a chain, because it may require the implementation to "break" the chaining optimization.

Does it makes sense? Do you think memory ordering be prohibited within a chain?

Comment thread content/bundles_intro.tex
@@ -0,0 +1,23 @@
\newtext{The performance of \openshmem programs that issue many consecutive and
small-sized communication routines might be improved by combining these
operations into fewer messages.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We don't use the term "message" elsewhere in the specification. Is there a different term we could use?

@davidozog davidozog Oct 29, 2021

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Maybe "operation"? Oops, too many "operations" 😉

Yes, this might need some wordsmithing... Maybe "... by combining these routines into fewer [underlying] operations in the [OpenSHMEM] runtime [/library]"?

Comment thread content/bundles_intro.tex
Comment on lines +4 to +6
The \emph{bundling routines} provide a convenient interface for indicating to
the \openshmem library that a series of operations on a communication context
are eligible for bundling-related optimization.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Who determines eligibility? Is it the application or the library? To nit-pick, I think it's the application that indicates suitability (e.g., now I will be issuing lots of nonblocking RMA operations), while it's the library and specification that determine eligibility (e.g, we cannot bundle blocking gets). Elsewhere, there's a comment from @bcernohous "that it's a bad idea to go into non-shmem code (like a long computation loop) without a stop." To me, this speaks to the suitability of the

I'll suggest something like:

The bundling routines provide a mechanism for an application to indicate to the OpenSHMEM library that it intends to issue a series of operations on a communication context that are suitable for bundling optimization.

Comment thread content/bundles_intro.tex
Comment on lines +11 to +13
\newtext{The bundling routines are \textit{hints} to the \openshmem library,
and they do not affect the completion or ordering semantics of any \openshmem
routines in the program.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
\newtext{The bundling routines are \textit{hints} to the \openshmem library,
and they do not affect the completion or ordering semantics of any \openshmem
routines in the program.
\newtext{The bundling routines are \textit{hints} to the \openshmem library;
they do not affect the completion or ordering semantics of any \openshmem
routines in the program.

Comment thread content/bundles_intro.tex
Comment on lines +21 to +23
Because bundling is performed with respect to an \openshmem communication
context, routines not performed on a communication context are ineligible for
bundling optimization.}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This seems (initially, at least) to be contradictory to the shmem_bundle_{start,stop} API, which indicates bundling on the default context. Do we mean routines like collectives?

@davidozog davidozog Oct 29, 2021

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Yes, exactly - like collectives. I would argue that the default context is indeed a communication context, but I see how this could be confusing on first glance. Maybe, "routines not performed on a valid communication context..."? I believe we refer to "valid" contexts (including the default) elsewhere in the spec.

Comment on lines +19 to +20
The \FUNC{shmem\_bundle\_start} routine provides a hint to the \openshmem
library to being applying bundling-related optimizations.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
The \FUNC{shmem\_bundle\_start} routine provides a hint to the \openshmem
library to being applying bundling-related optimizations.
The \FUNC{shmem\_bundle\_start} routine provides a hint to the \openshmem
library to begin applying bundling-related optimizations.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I also feel iffy about the expression "bundling-related optimizations." In the intro, we have "bundling phase," so maybe...

Suggested change
The \FUNC{shmem\_bundle\_start} routine provides a hint to the \openshmem
library to being applying bundling-related optimizations.
The \FUNC{shmem\_bundle\_start} routine provides a hint to the \openshmem
library to begin a bundling phase.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Agreed, thanks - and we should also do this in shmem_bundle_stop.

@nspark

nspark commented Oct 29, 2021

Copy link
Copy Markdown
Contributor

I agree with @jdinan's comment that this API may be a better fit for the "Communication Management Routines."

In that case, maybe the naming should be slightly revised; e.g., shmem_ctx_bundle_startshmem_ctx_start_bundle. But, this leaves shmem_bundle_start as something of an oddball.

Comment on lines +1 to +2
#include <shmem.h>
#include <stdlib.h>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
#include <shmem.h>
#include <stdlib.h>
#include <shmem.h>
#include <stdint.h>
#include <stdlib.h>

Comment on lines +4 to +6
#define N_UPDATES (1 << 20)
#define N_INDICES (1 << 10)
#define N_VALUES (1 << 31)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
#define N_UPDATES (1 << 20)
#define N_INDICES (1 << 10)
#define N_VALUES (1 << 31)
#define N_UPDATES (1lu << 20)
#define N_INDICES (1lu << 10)
#define N_VALUES (1lu << 31)


shmem_init();

uint64_t *table = shmem_malloc(N_INDICES * sizeof(uint64_t));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
uint64_t *table = shmem_malloc(N_INDICES * sizeof(uint64_t));
uint64_t *table = shmem_calloc(N_INDICES, sizeof(uint64_t));

size_t random_idx = rand() % N_INDICES;
uint64_t random_val = rand() % N_VALUES;
shmem_uint64_atomic_xor(&table[random_idx], random_val, random_pe);
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Minor: the indentations can be matched.


int mype = shmem_my_pe();
int npes = shmem_n_pes();

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Suggest adding srand(mype);

@nspark

nspark commented Oct 29, 2021

Copy link
Copy Markdown
Contributor

@naveen-rn suggested making bundling a property that could be enabled/disabled dynamically (i.e., not only at context creation), which would generalize the API for potential future dynamic properties on contexts.

@nspark

nspark commented Mar 14, 2022

Copy link
Copy Markdown
Contributor

@davidozog One case of interest to me is combining bundling with put-with-signal. I would like to think there's a good bit of room for optimization internal to an OpenSHMEM library.

For example, we often think of put-with-signal as roughly equivalent to:

shmem_putmem(..., pe);
shmem_fence();
shmem_set(&sigword, signal, pe);

(Note, we lack, and need, shmem_signal_set; see #382.)

In my mind, bundling + put-with-signal could effectively transform:

for (int i = 0; i < bound; i++)
  shmem_put_signal_nbi(..., &sigword, SHMEM_SIGNAL_SET, pe_targets[i]);

Into:

for (int i = 0; i < bound; i++)
  shmem_put_nbi(..., pe_targets[i]);
shmem_fence();
for (int i = 0; i < bound; i++)
  shmem_signal_set(&sigword, signal, pe_targets[i]);

Not every library would necessarily want to make such a transformation. But, I imagine some might find it advantageous.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants