backport: re PR libgomp/80822 (libgomp incorrect affinity when OMP_PLACES=threads)

Backported from mainline
	2017-05-30  Jakub Jelinek  <jakub@redhat.com>

	PR libgomp/80822
	* config/linux/affinity.c (gomp_affinity_init_level_1): New function.
	(gomp_affinity_init_level): Use it.  Always analyze the core and thread
	sibling lists, depending on level just pick up what CPUs to put
	together into a place vs. whether add multiple ordered places.

From-SVN: r248814
This commit is contained in:
Jakub Jelinek 2017-06-02 09:27:49 +02:00 committed by Jakub Jelinek
parent f829242273
commit 6484260ee8
2 changed files with 101 additions and 83 deletions

View File

@ -1,3 +1,14 @@
2017-06-02 Jakub Jelinek <jakub@redhat.com>
Backported from mainline
2017-05-30 Jakub Jelinek <jakub@redhat.com>
PR libgomp/80822
* config/linux/affinity.c (gomp_affinity_init_level_1): New function.
(gomp_affinity_init_level): Use it. Always analyze the core and thread
sibling lists, depending on level just pick up what CPUs to put
together into a place vs. whether add multiple ordered places.
2017-05-26 Jakub Jelinek <jakub@redhat.com> 2017-05-26 Jakub Jelinek <jakub@redhat.com>
Backported from mainline Backported from mainline

View File

@ -222,60 +222,32 @@ gomp_affinity_finalize_place_list (bool quiet)
return true; return true;
} }
bool static void
gomp_affinity_init_level (int level, unsigned long count, bool quiet) gomp_affinity_init_level_1 (int level, int this_level, unsigned long count,
cpu_set_t *copy, char *name, bool quiet)
{ {
unsigned long i, max = 8 * gomp_cpuset_size;
if (gomp_cpusetp)
{
unsigned long maxcount
= gomp_cpuset_popcount (gomp_cpuset_size, gomp_cpusetp);
if (count > maxcount)
count = maxcount;
}
gomp_places_list = gomp_affinity_alloc (count, quiet);
gomp_places_list_len = 0;
if (gomp_places_list == NULL)
return false;
/* SMT (threads). */
if (level == 1)
{
for (i = 0; i < max && gomp_places_list_len < count; i++)
if (CPU_ISSET_S (i, gomp_cpuset_size, gomp_cpusetp))
{
gomp_affinity_init_place (gomp_places_list[gomp_places_list_len]);
gomp_affinity_add_cpus (gomp_places_list[gomp_places_list_len],
i, 1, 0, true);
++gomp_places_list_len;
}
return true;
}
else
{
char name[sizeof ("/sys/devices/system/cpu/cpu/topology/"
"thread_siblings_list") + 3 * sizeof (unsigned long)];
size_t prefix_len = sizeof ("/sys/devices/system/cpu/cpu") - 1; size_t prefix_len = sizeof ("/sys/devices/system/cpu/cpu") - 1;
cpu_set_t *copy = gomp_alloca (gomp_cpuset_size);
FILE *f; FILE *f;
char *line = NULL; char *line = NULL;
size_t linelen = 0; size_t linelen = 0;
unsigned long i, max = 8 * gomp_cpuset_size;
memcpy (name, "/sys/devices/system/cpu/cpu", prefix_len);
memcpy (copy, gomp_cpusetp, gomp_cpuset_size);
for (i = 0; i < max && gomp_places_list_len < count; i++) for (i = 0; i < max && gomp_places_list_len < count; i++)
if (CPU_ISSET_S (i, gomp_cpuset_size, copy)) if (CPU_ISSET_S (i, gomp_cpuset_size, copy))
{ {
sprintf (name + prefix_len, "%lu/topology/%s_siblings_list", sprintf (name + prefix_len, "%lu/topology/%s_siblings_list",
i, level == 2 ? "thread" : "core"); i, this_level == 3 ? "core" : "thread");
f = fopen (name, "r"); f = fopen (name, "r");
if (f != NULL) if (f == NULL)
{ {
CPU_CLR_S (i, gomp_cpuset_size, copy);
continue;
}
if (getline (&line, &linelen, f) > 0) if (getline (&line, &linelen, f) > 0)
{ {
char *p = line; char *p = line;
bool seen_i = false;
void *pl = gomp_places_list[gomp_places_list_len]; void *pl = gomp_places_list[gomp_places_list_len];
if (level == this_level)
gomp_affinity_init_place (pl); gomp_affinity_init_place (pl);
while (*p && *p != '\n') while (*p && *p != '\n')
{ {
@ -293,35 +265,70 @@ gomp_affinity_init_level (int level, unsigned long count, bool quiet)
break; break;
} }
for (; first <= last; first++) for (; first <= last; first++)
if (CPU_ISSET_S (first, gomp_cpuset_size, copy) if (!CPU_ISSET_S (first, gomp_cpuset_size, copy))
&& gomp_affinity_add_cpus (pl, first, 1, 0, continue;
true)) else if (this_level == 3 && level < this_level)
gomp_affinity_init_level_1 (level, 2, count, copy,
name, quiet);
else
{
if (level == 1)
{
pl = gomp_places_list[gomp_places_list_len];
gomp_affinity_init_place (pl);
}
if (gomp_affinity_add_cpus (pl, first, 1, 0, true))
{ {
CPU_CLR_S (first, gomp_cpuset_size, copy); CPU_CLR_S (first, gomp_cpuset_size, copy);
if (first == i) if (level == 1)
seen_i = true; gomp_places_list_len++;
}
} }
if (*p == ',') if (*p == ',')
++p; ++p;
} }
if (seen_i) if (level == this_level
&& !CPU_ISSET_S (i, gomp_cpuset_size, copy))
gomp_places_list_len++; gomp_places_list_len++;
CPU_CLR_S (i, gomp_cpuset_size, copy);
} }
fclose (f); fclose (f);
} }
free (line);
}
bool
gomp_affinity_init_level (int level, unsigned long count, bool quiet)
{
char name[sizeof ("/sys/devices/system/cpu/cpu/topology/"
"thread_siblings_list") + 3 * sizeof (unsigned long)];
cpu_set_t *copy;
if (gomp_cpusetp)
{
unsigned long maxcount
= gomp_cpuset_popcount (gomp_cpuset_size, gomp_cpusetp);
if (count > maxcount)
count = maxcount;
} }
gomp_places_list = gomp_affinity_alloc (count, quiet);
gomp_places_list_len = 0;
if (gomp_places_list == NULL)
return false;
copy = gomp_alloca (gomp_cpuset_size);
strcpy (name, "/sys/devices/system/cpu/cpu");
memcpy (copy, gomp_cpusetp, gomp_cpuset_size);
gomp_affinity_init_level_1 (level, 3, count, copy, name, quiet);
if (gomp_places_list_len == 0) if (gomp_places_list_len == 0)
{ {
if (!quiet) if (!quiet)
gomp_error ("Error reading %s topology", gomp_error ("Error reading core/socket topology");
level == 2 ? "core" : "socket");
free (gomp_places_list); free (gomp_places_list);
gomp_places_list = NULL; gomp_places_list = NULL;
return false; return false;
} }
return true; return true;
}
return false;
} }
void void