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>
Backported from mainline

View File

@ -222,10 +222,87 @@ gomp_affinity_finalize_place_list (bool quiet)
return true;
}
static void
gomp_affinity_init_level_1 (int level, int this_level, unsigned long count,
cpu_set_t *copy, char *name, bool quiet)
{
size_t prefix_len = sizeof ("/sys/devices/system/cpu/cpu") - 1;
FILE *f;
char *line = NULL;
size_t linelen = 0;
unsigned long i, max = 8 * gomp_cpuset_size;
for (i = 0; i < max && gomp_places_list_len < count; i++)
if (CPU_ISSET_S (i, gomp_cpuset_size, copy))
{
sprintf (name + prefix_len, "%lu/topology/%s_siblings_list",
i, this_level == 3 ? "core" : "thread");
f = fopen (name, "r");
if (f == NULL)
{
CPU_CLR_S (i, gomp_cpuset_size, copy);
continue;
}
if (getline (&line, &linelen, f) > 0)
{
char *p = line;
void *pl = gomp_places_list[gomp_places_list_len];
if (level == this_level)
gomp_affinity_init_place (pl);
while (*p && *p != '\n')
{
unsigned long first, last;
errno = 0;
first = strtoul (p, &p, 10);
if (errno)
break;
last = first;
if (*p == '-')
{
errno = 0;
last = strtoul (p + 1, &p, 10);
if (errno || last < first)
break;
}
for (; first <= last; first++)
if (!CPU_ISSET_S (first, gomp_cpuset_size, copy))
continue;
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);
if (level == 1)
gomp_places_list_len++;
}
}
if (*p == ',')
++p;
}
if (level == this_level
&& !CPU_ISSET_S (i, gomp_cpuset_size, copy))
gomp_places_list_len++;
CPU_CLR_S (i, gomp_cpuset_size, copy);
}
fclose (f);
}
free (line);
}
bool
gomp_affinity_init_level (int level, unsigned long count, bool quiet)
{
unsigned long i, max = 8 * gomp_cpuset_size;
char name[sizeof ("/sys/devices/system/cpu/cpu/topology/"
"thread_siblings_list") + 3 * sizeof (unsigned long)];
cpu_set_t *copy;
if (gomp_cpusetp)
{
@ -238,90 +315,20 @@ gomp_affinity_init_level (int level, unsigned long count, bool 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;
cpu_set_t *copy = gomp_alloca (gomp_cpuset_size);
FILE *f;
char *line = NULL;
size_t linelen = 0;
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++)
if (CPU_ISSET_S (i, gomp_cpuset_size, copy))
{
sprintf (name + prefix_len, "%lu/topology/%s_siblings_list",
i, level == 2 ? "thread" : "core");
f = fopen (name, "r");
if (f != NULL)
{
if (getline (&line, &linelen, f) > 0)
{
char *p = line;
bool seen_i = false;
void *pl = gomp_places_list[gomp_places_list_len];
gomp_affinity_init_place (pl);
while (*p && *p != '\n')
{
unsigned long first, last;
errno = 0;
first = strtoul (p, &p, 10);
if (errno)
break;
last = first;
if (*p == '-')
{
errno = 0;
last = strtoul (p + 1, &p, 10);
if (errno || last < first)
break;
}
for (; first <= last; first++)
if (CPU_ISSET_S (first, gomp_cpuset_size, copy)
&& gomp_affinity_add_cpus (pl, first, 1, 0,
true))
{
CPU_CLR_S (first, gomp_cpuset_size, copy);
if (first == i)
seen_i = true;
}
if (*p == ',')
++p;
}
if (seen_i)
gomp_places_list_len++;
}
fclose (f);
}
}
if (gomp_places_list_len == 0)
{
if (!quiet)
gomp_error ("Error reading %s topology",
level == 2 ? "core" : "socket");
free (gomp_places_list);
gomp_places_list = NULL;
return false;
}
return true;
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 (!quiet)
gomp_error ("Error reading core/socket topology");
free (gomp_places_list);
gomp_places_list = NULL;
return false;
}
return false;
return true;
}
void