Map fusion error, by design?

Map fusion error, by design?

Portrait de tuinenga

With this example...

void step1(f32 &val, f32 &arg)
{
arg = (arg + neighbor(arg, 1))*0.5;
};
void step2(f32 &val, f32 &arg)
{
val = (arg + neighbor(arg, 1))*0.5;
};
void steps(f32 &val, f32 &arg)
{
arg = (arg + neighbor(arg, 1))*0.5;
val = (arg + neighbor(arg, 1))*0.5;
};
void do_steps(dense &val, dense &arg)
{
#if 1
arbb::map(step1)(val, arg);
arbb::map(step2)(val, arg);
#else
arbb::map(steps)(val, arg);
#endif
};

...compiling and running with"step1" & "step2" works, but instead with the combined "steps" generates the runtime error "INCORRECT_MAP_USAGE:Invalid use of neighbour-access function on variable other than distributed input"

This leads me to think I don't fully understand how map() is constrained to insulate againste.g. data races. Please describe why the"steps" usage is invalid and anything else we should know about map().

Best regards,
- paul

6 posts / 0 nouveau(x)
Dernière contribution
Reportez-vous à notre Notice d'optimisation pour plus d'informations sur les choix et l'optimisation des performances dans les produits logiciels Intel.
Portrait de Zhang Z (Intel)

Hi Paul,

The usage of "map" in "steps" is invalid because the two statements create a read-after-write dependency on "arg". Specifically, the neighbor() call in the second statement reads the output of the first statement in another map() invocation instance. And this is explicitly disallowed in the API reference manual.

All we need to know about map() is documented here (link). The paragraph that disallows this type of usage is copied below:

The arbb::neighbor() function does not allow reading the outputs of other arbb::map()
invocation instances, because it always returns the element as it was
before the function began executing. This allows such invocations to
execute in parallel, because they remain independent.

Hope this helps.

Zhang

Portrait de admin

It is curious that amodifed example, swapping the linesbut still violating the reference manual paragraph (above), runs...

void steps(f32 &val, f32 &arg)
{
val = (arg + neighbor(arg, 1))*0.5;
arg = (arg + neighbor(arg, 1))*0.5;
};

...and no error is generated during execution.Howeverthe"val" resultschange if the 2nd statement is commented out, which is unexpected.

Best regards,
- paul

Portrait de Zhang Z (Intel)

I could not exactly reproduce the problem. When I ran the code I saw the "val" results to be the same, commenting out the 2nd statement or not. Would you please send me or post here your code that produces unexpected results?

Your revised example can be equivalently written as:

void steps(f32& val, f32& arg)
{
f32 temp = (arg + neighbor(arg, 1))*0.5;
val = temp;
arg = temp;
}

This does not violate the restrictions stated in the reference manual. However, the original example (where the two statements are not swapped) cannot be written this way. I guess this makes the difference.

Thanks,
Zhang

Portrait de tuinenga

Thank you for the advice, but it's a nonsense calculation just to ferret out undocumented operation. Here's the main:

dense vfoo;
vfoo = indices(f32(0.), 5, f32(1.));
dense vbar;
vbar = fill(f32(), 5);

const closure &, dense &)> clo = capture(do_steps);
clo(vbar, vfoo); // just to make sure
{
const scoped_timer timer(ptime, scoped_timer::unit_us);
clo(vbar, vfoo);
}
const_range read_range = vbar.read_only_range();
printf("\n\n** %g %g %g \n\n", (double)read_range[0], (double)read_range[1], (double)read_range[2]);

With both lines in "steps" the console output is: ** 1 2 3

Without 2nd line, the output is: ** 0.5 1.5 2.5

But now I realize . . . my main runs the function twice, altering vfoo on the first pass. Mystery solved! The problem was "above the keyboard." Sorry to waste your time on that part.

Still,my opinion isthe documentation should read:
"The arbb::neighbor() function does not allow reading the outputs of previous arbb::map() invocation instances,..."
or somehow made consistent with the intent and operation of ArBB.

Best regards,
- paul

Portrait de tuinenga

I am reminded of wisdom from Jon Bentley's 1988 classic "More Programming Pearls" 6.3 "Debugging":

"Of all my programming bugs, 80% are syntax errors. Of the remaining 20%, 80% are trivial logical errors. Of the remaining 4%, 80% are pointer errors. And the remaining 0.8% are hard."

Cheers,
- paul

Connectez-vous pour laisser un commentaire.