* [PATCH, libgomp] Fix chunk_size<1 for dynamic schedule @ 2022-06-23 15:47 Chung-Lin Tang 2022-06-28 14:06 ` Jakub Jelinek 0 siblings, 1 reply; 8+ messages in thread From: Chung-Lin Tang @ 2022-06-23 15:47 UTC (permalink / raw) To: gcc-patches, Catherine Moore, Tobias Burnus [-- Attachment #1: Type: text/plain, Size: 802 bytes --] Hi Jakub, with the way that chunk_size < 1 is handled for gomp_iter_dynamic_next: (1) chunk_size <= -1: wraps into large unsigned value, seems to work though. (2) chunk_size == 0: infinite loop The (2) behavior is obviously not desired. This patch fixes this by changing the chunk_size initialization in gomp_loop_init to "max(1,chunk_size)" The OMP_SCHEDULE parsing in libgomp/env.c has also been adjusted to reject negative values. Tested without regressions, and a new testcase for the infinite loop behavior added. Okay for trunk? Thanks, Chung-Lin libgomp/ChangeLog: * env.c (parse_schedule): Make negative values invalid for chunk_size. * loop.c (gomp_loop_init): For non-STATIC schedule and chunk_size <= 0, set initialized chunk_size to 1. * testsuite/libgomp.c/loop-28.c: New test. [-- Attachment #2: chunk_size.patch --] [-- Type: text/plain, Size: 1411 bytes --] diff --git a/libgomp/env.c b/libgomp/env.c index 1c4ee894515..dff07617e15 100644 --- a/libgomp/env.c +++ b/libgomp/env.c @@ -182,6 +182,8 @@ parse_schedule (void) goto invalid; errno = 0; + if (*env == '-') + goto invalid; value = strtoul (env, &end, 10); if (errno || end == env) goto invalid; diff --git a/libgomp/loop.c b/libgomp/loop.c index be85162bb1e..018b4e9a8bd 100644 --- a/libgomp/loop.c +++ b/libgomp/loop.c @@ -41,7 +41,7 @@ gomp_loop_init (struct gomp_work_share *ws, long start, long end, long incr, enum gomp_schedule_type sched, long chunk_size) { ws->sched = sched; - ws->chunk_size = chunk_size; + ws->chunk_size = (sched == GFS_STATIC || chunk_size > 1) ? chunk_size : 1; /* Canonicalize loops that have zero iterations to ->next == ->end. */ ws->end = ((incr > 0 && start > end) || (incr < 0 && start < end)) ? start : end; diff --git a/libgomp/testsuite/libgomp.c/loop-28.c b/libgomp/testsuite/libgomp.c/loop-28.c new file mode 100644 index 00000000000..e3f852046f4 --- /dev/null +++ b/libgomp/testsuite/libgomp.c/loop-28.c @@ -0,0 +1,17 @@ +/* { dg-do run } */ +/* { dg-timeout 10 } */ + +void __attribute__((noinline)) +foo (int a[], int n, int chunk_size) +{ + #pragma omp parallel for schedule (dynamic,chunk_size) + for (int i = 0; i < n; i++) + a[i] = i; +} + +int main (void) +{ + int a[100]; + foo (a, 100, 0); + return 0; +} ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH, libgomp] Fix chunk_size<1 for dynamic schedule 2022-06-23 15:47 [PATCH, libgomp] Fix chunk_size<1 for dynamic schedule Chung-Lin Tang @ 2022-06-28 14:06 ` Jakub Jelinek 2022-06-28 15:07 ` Jakub Jelinek 2022-08-04 13:17 ` Chung-Lin Tang 0 siblings, 2 replies; 8+ messages in thread From: Jakub Jelinek @ 2022-06-28 14:06 UTC (permalink / raw) To: Chung-Lin Tang; +Cc: gcc-patches, Catherine Moore, Tobias Burnus On Thu, Jun 23, 2022 at 11:47:59PM +0800, Chung-Lin Tang wrote: > with the way that chunk_size < 1 is handled for gomp_iter_dynamic_next: > > (1) chunk_size <= -1: wraps into large unsigned value, seems to work though. > (2) chunk_size == 0: infinite loop > > The (2) behavior is obviously not desired. This patch fixes this by changing Why? It is a user error, undefined behavior, we shouldn't slow down valid code for users who don't bother reading the standard. E.g. OpenMP 5.1 [132:14] says clearly: "chunk_size must be a loop invariant integer expression with a positive value." and omp_set_schedule for chunk_size < 1 should use a default value (which it does). For OMP_SCHEDULE the standard says it is implementation-defined what happens if the format isn't the specified one, so I guess the env.c change could be acceptable (though without it it is fine too), but the loop.c change is wrong. Note, if the loop.c change would be ok, you'd need to also change loop_ull.c too. Jakub ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH, libgomp] Fix chunk_size<1 for dynamic schedule 2022-06-28 14:06 ` Jakub Jelinek @ 2022-06-28 15:07 ` Jakub Jelinek 2022-08-04 13:17 ` Chung-Lin Tang 1 sibling, 0 replies; 8+ messages in thread From: Jakub Jelinek @ 2022-06-28 15:07 UTC (permalink / raw) To: Chung-Lin Tang, Tobias Burnus, gcc-patches On Tue, Jun 28, 2022 at 04:06:14PM +0200, Jakub Jelinek via Gcc-patches wrote: > On Thu, Jun 23, 2022 at 11:47:59PM +0800, Chung-Lin Tang wrote: > > with the way that chunk_size < 1 is handled for gomp_iter_dynamic_next: > > > > (1) chunk_size <= -1: wraps into large unsigned value, seems to work though. > > (2) chunk_size == 0: infinite loop > > > > The (2) behavior is obviously not desired. This patch fixes this by changing > > Why? It is a user error, undefined behavior, we shouldn't slow down valid > code for users who don't bother reading the standard. > > E.g. OpenMP 5.1 [132:14] says clearly: > "chunk_size must be a loop invariant integer expression with a positive > value." > and omp_set_schedule for chunk_size < 1 should use a default value (which it > does). > > For OMP_SCHEDULE the standard says it is implementation-defined what happens > if the format isn't the specified one, so I guess the env.c change > could be acceptable (though without it it is fine too), but the Though, seems we quietly transform the only problematic value (0) in there to 1 for selected schedules which don't accept 0 as "unspecified" and for the negative values, we'll have large ulong chunk sizes which is fine. If we really want help people debugging their programs, we could introduce something like -fsanitize=openmp that would add runtime instrumentation of a lot of OpenMP restrictions and could diagnose it with nice diagnostics, perhaps using some extra library and with runtime checks in generated code. Jakub ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH, libgomp] Fix chunk_size<1 for dynamic schedule 2022-06-28 14:06 ` Jakub Jelinek 2022-06-28 15:07 ` Jakub Jelinek @ 2022-08-04 13:17 ` Chung-Lin Tang 2022-08-04 13:31 ` Koning, Paul 2022-09-13 14:07 ` Jakub Jelinek 1 sibling, 2 replies; 8+ messages in thread From: Chung-Lin Tang @ 2022-08-04 13:17 UTC (permalink / raw) To: Jakub Jelinek; +Cc: gcc-patches, Catherine Moore, Tobias Burnus [-- Attachment #1: Type: text/plain, Size: 1719 bytes --] On 2022/6/28 10:06 PM, Jakub Jelinek wrote: > On Thu, Jun 23, 2022 at 11:47:59PM +0800, Chung-Lin Tang wrote: >> with the way that chunk_size < 1 is handled for gomp_iter_dynamic_next: >> >> (1) chunk_size <= -1: wraps into large unsigned value, seems to work though. >> (2) chunk_size == 0: infinite loop >> >> The (2) behavior is obviously not desired. This patch fixes this by changing > > Why? It is a user error, undefined behavior, we shouldn't slow down valid > code for users who don't bother reading the standard. This is loop init code, not per-iteration. The overhead really isn't that much. The question should be, if GCC having infinite loop behavior is reasonable, even if it is undefined in the spec. > E.g. OpenMP 5.1 [132:14] says clearly: > "chunk_size must be a loop invariant integer expression with a positive > value." > and omp_set_schedule for chunk_size < 1 should use a default value (which it > does). > > For OMP_SCHEDULE the standard says it is implementation-defined what happens > if the format isn't the specified one, so I guess the env.c change > could be acceptable (though without it it is fine too), but the > loop.c change is wrong. Note, if the loop.c change would be ok, you'd > need to also change loop_ull.c too. I've updated the patch to add the same changes for libgomp/loop_ull.c and updated the testcase too. Tested on mainline trunk without regressions. Thanks, Chung-Lin libgomp/ChangeLog: * env.c (parse_schedule): Make negative values invalid for chunk_size. * loop.c (gomp_loop_init): For non-STATIC schedule and chunk_size <= 0, set initialized chunk_size to 1. * loop_ull.c (gomp_loop_ull_init): Likewise. * testsuite/libgomp.c/loop-28.c: New test. [-- Attachment #2: chunk_size-v2.patch --] [-- Type: text/plain, Size: 2091 bytes --] diff --git a/libgomp/env.c b/libgomp/env.c index 1c4ee894515..dff07617e15 100644 --- a/libgomp/env.c +++ b/libgomp/env.c @@ -182,6 +182,8 @@ parse_schedule (void) goto invalid; errno = 0; + if (*env == '-') + goto invalid; value = strtoul (env, &end, 10); if (errno || end == env) goto invalid; diff --git a/libgomp/loop.c b/libgomp/loop.c index be85162bb1e..018b4e9a8bd 100644 --- a/libgomp/loop.c +++ b/libgomp/loop.c @@ -41,7 +41,7 @@ gomp_loop_init (struct gomp_work_share *ws, long start, long end, long incr, enum gomp_schedule_type sched, long chunk_size) { ws->sched = sched; - ws->chunk_size = chunk_size; + ws->chunk_size = (sched == GFS_STATIC || chunk_size > 1) ? chunk_size : 1; /* Canonicalize loops that have zero iterations to ->next == ->end. */ ws->end = ((incr > 0 && start > end) || (incr < 0 && start < end)) ? start : end; diff --git a/libgomp/loop_ull.c b/libgomp/loop_ull.c index 602737296d4..74ddb1bd623 100644 --- a/libgomp/loop_ull.c +++ b/libgomp/loop_ull.c @@ -43,7 +43,7 @@ gomp_loop_ull_init (struct gomp_work_share *ws, bool up, gomp_ull start, gomp_ull chunk_size) { ws->sched = sched; - ws->chunk_size_ull = chunk_size; + ws->chunk_size_ull = (sched == GFS_STATIC || chunk_size > 1) ? chunk_size : 1; /* Canonicalize loops that have zero iterations to ->next == ->end. */ ws->end_ull = ((up && start > end) || (!up && start < end)) ? start : end; diff --git a/libgomp/testsuite/libgomp.c/loop-28.c b/libgomp/testsuite/libgomp.c/loop-28.c new file mode 100644 index 00000000000..664842e27aa --- /dev/null +++ b/libgomp/testsuite/libgomp.c/loop-28.c @@ -0,0 +1,21 @@ +/* { dg-do run } */ +/* { dg-timeout 10 } */ + +void __attribute__((noinline)) +foo (int a[], int n, int chunk_size) +{ + #pragma omp parallel for schedule (dynamic,chunk_size) + for (int i = 0; i < n; i++) + a[i] = i; + + #pragma omp parallel for schedule (dynamic,chunk_size) + for (unsigned long long i = 0; i < n; i++) + a[i] = i; +} + +int main (void) +{ + int a[100]; + foo (a, 100, 0); + return 0; +} ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH, libgomp] Fix chunk_size<1 for dynamic schedule 2022-08-04 13:17 ` Chung-Lin Tang @ 2022-08-04 13:31 ` Koning, Paul 2022-08-26 8:15 ` [PING] " Chung-Lin Tang 2022-09-13 14:07 ` Jakub Jelinek 1 sibling, 1 reply; 8+ messages in thread From: Koning, Paul @ 2022-08-04 13:31 UTC (permalink / raw) To: Chung-Lin Tang; +Cc: Jakub Jelinek, Tobias Burnus, GCC Patches > On Aug 4, 2022, at 9:17 AM, Chung-Lin Tang <cltang@codesourcery.com> wrote: > > On 2022/6/28 10:06 PM, Jakub Jelinek wrote: >> On Thu, Jun 23, 2022 at 11:47:59PM +0800, Chung-Lin Tang wrote: >>> with the way that chunk_size < 1 is handled for gomp_iter_dynamic_next: >>> >>> (1) chunk_size <= -1: wraps into large unsigned value, seems to work though. >>> (2) chunk_size == 0: infinite loop >>> >>> The (2) behavior is obviously not desired. This patch fixes this by changing >> Why? It is a user error, undefined behavior, we shouldn't slow down valid >> code for users who don't bother reading the standard. > > This is loop init code, not per-iteration. The overhead really isn't that much. > > The question should be, if GCC having infinite loop behavior is reasonable, > even if it is undefined in the spec. I wouldn't think so. The way I see "undefined code" is that you can't complain about "wrong code" produced by the compiler. But for the compiler to malfunction on wrong input is an entirely differerent matter. For one thing, it's hard to fix your code if the compiler fails. How would you locate the offending source line? paul ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PING] Re: [PATCH, libgomp] Fix chunk_size<1 for dynamic schedule 2022-08-04 13:31 ` Koning, Paul @ 2022-08-26 8:15 ` Chung-Lin Tang 2022-09-09 10:08 ` [PING x2] " Chung-Lin Tang 0 siblings, 1 reply; 8+ messages in thread From: Chung-Lin Tang @ 2022-08-26 8:15 UTC (permalink / raw) To: Koning, Paul; +Cc: Jakub Jelinek, Tobias Burnus, GCC Patches On 2022/8/4 9:31 PM, Koning, Paul wrote: > > >> On Aug 4, 2022, at 9:17 AM, Chung-Lin Tang <cltang@codesourcery.com> wrote: >> >> On 2022/6/28 10:06 PM, Jakub Jelinek wrote: >>> On Thu, Jun 23, 2022 at 11:47:59PM +0800, Chung-Lin Tang wrote: >>>> with the way that chunk_size < 1 is handled for gomp_iter_dynamic_next: >>>> >>>> (1) chunk_size <= -1: wraps into large unsigned value, seems to work though. >>>> (2) chunk_size == 0: infinite loop >>>> >>>> The (2) behavior is obviously not desired. This patch fixes this by changing >>> Why? It is a user error, undefined behavior, we shouldn't slow down valid >>> code for users who don't bother reading the standard. >> >> This is loop init code, not per-iteration. The overhead really isn't that much. >> >> The question should be, if GCC having infinite loop behavior is reasonable, >> even if it is undefined in the spec. > > I wouldn't think so. The way I see "undefined code" is that you can't complain about "wrong code" produced by the compiler. But for the compiler to malfunction on wrong input is an entirely differerent matter. For one thing, it's hard to fix your code if the compiler fails. How would you locate the offending source line? > > paul Ping? ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PING x2] Re: [PATCH, libgomp] Fix chunk_size<1 for dynamic schedule 2022-08-26 8:15 ` [PING] " Chung-Lin Tang @ 2022-09-09 10:08 ` Chung-Lin Tang 0 siblings, 0 replies; 8+ messages in thread From: Chung-Lin Tang @ 2022-09-09 10:08 UTC (permalink / raw) To: Koning, Paul, Jakub Jelinek; +Cc: Tobias Burnus, GCC Patches On 2022/8/26 4:15 PM, Chung-Lin Tang wrote: > On 2022/8/4 9:31 PM, Koning, Paul wrote: >> >> >>> On Aug 4, 2022, at 9:17 AM, Chung-Lin Tang <cltang@codesourcery.com> wrote: >>> >>> On 2022/6/28 10:06 PM, Jakub Jelinek wrote: >>>> On Thu, Jun 23, 2022 at 11:47:59PM +0800, Chung-Lin Tang wrote: >>>>> with the way that chunk_size < 1 is handled for gomp_iter_dynamic_next: >>>>> >>>>> (1) chunk_size <= -1: wraps into large unsigned value, seems to work though. >>>>> (2) chunk_size == 0: infinite loop >>>>> >>>>> The (2) behavior is obviously not desired. This patch fixes this by changing >>>> Why? It is a user error, undefined behavior, we shouldn't slow down valid >>>> code for users who don't bother reading the standard. >>> >>> This is loop init code, not per-iteration. The overhead really isn't that much. >>> >>> The question should be, if GCC having infinite loop behavior is reasonable, >>> even if it is undefined in the spec. >> >> I wouldn't think so. The way I see "undefined code" is that you can't complain about "wrong code" produced by the compiler. But for the compiler to malfunction on wrong input is an entirely differerent matter. For one thing, it's hard to fix your code if the compiler fails. How would you locate the offending source line? >> >> paul > > Ping? Ping x2. ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH, libgomp] Fix chunk_size<1 for dynamic schedule 2022-08-04 13:17 ` Chung-Lin Tang 2022-08-04 13:31 ` Koning, Paul @ 2022-09-13 14:07 ` Jakub Jelinek 1 sibling, 0 replies; 8+ messages in thread From: Jakub Jelinek @ 2022-09-13 14:07 UTC (permalink / raw) To: Chung-Lin Tang; +Cc: Tobias Burnus, gcc-patches On Thu, Aug 04, 2022 at 09:17:09PM +0800, Chung-Lin Tang wrote: > On 2022/6/28 10:06 PM, Jakub Jelinek wrote: > > On Thu, Jun 23, 2022 at 11:47:59PM +0800, Chung-Lin Tang wrote: > > > with the way that chunk_size < 1 is handled for gomp_iter_dynamic_next: > > > > > > (1) chunk_size <= -1: wraps into large unsigned value, seems to work though. > > > (2) chunk_size == 0: infinite loop > > > > > > The (2) behavior is obviously not desired. This patch fixes this by changing > > > > Why? It is a user error, undefined behavior, we shouldn't slow down valid > > code for users who don't bother reading the standard. > > This is loop init code, not per-iteration. The overhead really isn't that much. But still, we slow down valid code for the sake of garbage. That is a task for sanitizers, not production libraries. > > The question should be, if GCC having infinite loop behavior is reasonable, > even if it is undefined in the spec. Sure, it is perfectly valid implementation of the undefined behavior. UB can leads to tons of surprising behavior, hangs etc. and this is exactly the same category. On Thu, Aug 04, 2022 at 01:31:50PM +0000, Koning, Paul via Gcc-patches wrote: > I wouldn't think so. The way I see "undefined code" is that you can't complain > about "wrong code" produced by the compiler. But for the compiler to malfunction > on wrong input is an entirely differerent matter. For one thing, it's hard to fix > your code if the compiler fails. How would you locate the offending source line? The compiler isn't malfunctioning here. It is similar to calling a library function with bogus arguments, say memcpy with NULL source or destination or some invalid pointer not pointing anywhere valid, etc. The spec clearly says zero or negative chunk size is not valid, you use it, you get what you ask for. Furthermore, it is easy to find out when it hangs on which construct it is and check if that construct is valid. I'm strongly against slowing valid code for this. If you want to implement -fsanitize=openmp and either in that case perform checks on the generated code side or link with an instrumented version of libgomp that explains users what errors they do, that is fine. Jakub ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2022-09-13 14:08 UTC | newest] Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2022-06-23 15:47 [PATCH, libgomp] Fix chunk_size<1 for dynamic schedule Chung-Lin Tang 2022-06-28 14:06 ` Jakub Jelinek 2022-06-28 15:07 ` Jakub Jelinek 2022-08-04 13:17 ` Chung-Lin Tang 2022-08-04 13:31 ` Koning, Paul 2022-08-26 8:15 ` [PING] " Chung-Lin Tang 2022-09-09 10:08 ` [PING x2] " Chung-Lin Tang 2022-09-13 14:07 ` Jakub Jelinek
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).