Software Archive
Read-only legacy content
17060 Discussions

Feature request: warn on stray global variables in spawned routines

mecej4
Honored Contributor III
369 Views
CILK gives one an almost effortless way to speed up programs by converting serial to multithreaded code. There is a minor annoyance that I request help with.

I usually develop without CILK first. Once in a while, I will have some global counters that I increment inside heavily used functions. After the program is debugged I usually remove these variables before CILK-izing the code, but once in a while one or two get left behind, and when the multithreaded program is run the speed increase is disappointing because of the different threads contending for access to the global variables. Sometimes the program results are wrong, and one needs to remember that one source of error is writing to global variables without securing sole access.

If the multithreaded program runs more slowly than the serial version, I can take it as a tell-tale sign that there are some orphan global variables in my sources. If not, and it is not clear why parallelization has not worked well, I can fire up Intel Inspector and look at the program, but this is a rather time-consuming way of locating those wayward variables.

My request: would it be possible for the compiler, when it sees global variables in a function that is invoked with a "cilk_spawn" prefix elsewhere, to issue a warning that global variables can cause problems when written to with no discipline in multithreaded programs?

Thanks.
0 Kudos
7 Replies
Brandon_H_Intel
Employee
369 Views
You can use /Qdiag-enable:thread (Windows*) or -diag-enable thread (Linux*) to enable a diagnostic denoting references to global variables in a particular source file, but there's no way currently to limit this to the scope of a Cilk Plus cilk_spawn or cilk_for. This is a great feature request, I think, so I'll create one and update this thread as our front end team investigates this.
0 Kudos
Brandon_H_Intel
Employee
369 Views
Static Security Analysis (a Parallel Studio XE feature) or Parallel Lint (a Parallel Composer only feature) may also identify this, and may do it better than a compiler diagnostic since it would catch cases where a cilk_spawn'ed function is defined in a different source module from the cilk_spawn call, so I would recommend trying that as well.
0 Kudos
mecej4
Honored Contributor III
369 Views
Thanks for your suggestions.

The /Qdiag-enable:thread option does, indeed, help, but it has the drawback of issuing warnings even for legitimate and harmless uses of global variables outside the scope of a cilk_spawn directive. At times, the noise to signal ratio becomes a little too high to bear. A /Qdiag-enable:cilk_thread option, which does the necessary filtering, is what I requested.
0 Kudos
Barry_T_Intel
Employee
369 Views
The compiler may not be able to know if this access is safe and give you a lot of false positives. As you noted, Inspector (and Cilkscreen) are the best ways to handle this kind of error.

- Barry
0 Kudos
Pablo_H_Intel
Employee
369 Views
This would be a nice feature if it can be reasonably implemented. The challenge is in determining what the compiler can reasonably analyze so that it catches enough important cases to be useful but not so many false positives as to negate the advantages. It might be reasonable, for example to warn of any write to a global variable within a spawned function or the continuation of a spawn. You will get false positives, of course, since writing to a global variable in parallel code can be done without racing (e.g., if the same variable is not read or written from another strand). There will also be false negatives, as the compiler cannot tell from looking at a function's body whether that function will be spawned. Only in cases where the compiler sees both the spawn and the spawned function in the same compilation unit can the compiler easily detect global variable accesses from spawned code. Even then, if the function body comes before the spawn in the compilation unit, the compiler could not issue the warning unless it kept track of every global access in every function on the off chance that that function might be spawned.

For all of these reasons, I suspect that this feature might best be handled by a separate static analysis tool, in combination with dynamic tools like Cilkscreen and Inspector. If firing up these tools is too time-consuming, as you say, then perhaps another suggestion we can forward is to provide an easier, less-time-consuming way to to invoke these tools, at least for specific, common types of analysis. (Cilkscreen, by the way, is easily invoked from the command line and provides a yes/no answer regarding races. It is not, alas, a static anlysis tools and its accuracy, as well as speed, is limited by the quality of your test program and/or data set.)
0 Kudos
mecej4
Honored Contributor III
369 Views
I appreciate your penetrating analysis. You have covered most of the issues involved. Thank you.

> There will also be false negatives, as the compiler cannot tell from looking at a function's body whether that function will be spawned.

True. However, if there were a spawnable or some such attribute that the compiler would recognize, in analogy with volatile, the programmer could help the compiler by declaring that attribute for routines that she/he intends to spawn. This attribute would be ignored by the compiler if the -cilk-serialize option were used.
0 Kudos
Brandon_H_Intel
Employee
369 Views
Hi mecej4,

After coming back to this and thinking about it some more, if you are willing to do a code change for functions that you want checked, you could use the #pragma warning to seletively enable/disable warning 1711 which is the warning number for these shared variable accesses. Just do:

[cpp]#pragma warning(1 : 1711)
/* functions or code you want checked */
#pragma warning(default : 1711)
[/cpp]

I'm curious if that would be enough to meet your needs.
0 Kudos
Reply