summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrian Chadd <adrian@FreeBSD.org>2015-04-27 04:50:20 +0000
committerAdrian Chadd <adrian@FreeBSD.org>2015-04-27 04:50:20 +0000
commit8ba312a3fafbcf0d11c3d02bdd95d42bea14b81e (patch)
treea221277bbc5d4c9a757434fe645fcef16a321e90
parentImplement the FreeBSD specific pieces for thread affinity for OpenMP. (diff)
Implement the FreeBSD specific pieces for thread affinity for OpenMP.
Upstream gcc 4.8 doesn't have support for this - it'll create threads, but it won't do any of the thread affinity stuff for FreeBSD. This allows for OMP_PROC_BIND=true to bind threads to their initial CPUs, leading to some pretty drastic improvements in performance for certain NUMA workloads. Approved by: gerald Sponsored by: Norse Corp, Inc.
Notes
Notes: svn path=/head/; revision=384815
-rw-r--r--lang/gcc48/Makefile1
-rw-r--r--lang/gcc48/files/patch-libgomp-freebsd-affinity117
-rw-r--r--lang/gcc48/files/patch-libgomp-posix-affinity18
3 files changed, 136 insertions, 0 deletions
diff --git a/lang/gcc48/Makefile b/lang/gcc48/Makefile
index 5605336aedc6..26ab12791bff 100644
--- a/lang/gcc48/Makefile
+++ b/lang/gcc48/Makefile
@@ -3,6 +3,7 @@
PORTNAME= gcc
PORTVERSION= 4.8.5.s20150402
+PORTREVISION= 1
CATEGORIES= lang java
MASTER_SITES= ${MASTER_SITE_GCC}
MASTER_SITE_SUBDIR= snapshots/${DISTVERSION}
diff --git a/lang/gcc48/files/patch-libgomp-freebsd-affinity b/lang/gcc48/files/patch-libgomp-freebsd-affinity
new file mode 100644
index 000000000000..7b35399a66a2
--- /dev/null
+++ b/lang/gcc48/files/patch-libgomp-freebsd-affinity
@@ -0,0 +1,117 @@
+--- libgomp/config/bsd/freebsd_affinity.c.orig 2015-04-26 05:29:16.795040000 -0700
++++ libgomp/config/bsd/freebsd_affinity.c 2015-04-26 05:29:03.462728000 -0700
+@@ -0,0 +1,114 @@
++/* Copyright (C) 2015 Free Software Foundation, Inc.
++ Contributed by Adrian Chadd <adrian@FreeBSD.org>.
++ Based on work by Jakub Jelinek <jakub@redhat.com>.
++
++ This file is part of the GNU OpenMP Library (libgomp).
++
++ Libgomp is free software; you can redistribute it and/or modify it
++ under the terms of the GNU General Public License as published by
++ the Free Software Foundation; either version 3, or (at your option)
++ any later version.
++
++ Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
++ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
++ FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ more details.
++
++ Under Section 7 of GPL version 3, you are granted additional
++ permissions described in the GCC Runtime Library Exception, version
++ 3.1, as published by the Free Software Foundation.
++
++ You should have received a copy of the GNU General Public License and
++ a copy of the GCC Runtime Library Exception along with this program;
++ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
++ <http://www.gnu.org/licenses/>. */
++
++/* This is a FreeBSD specific implementation of a CPU affinity setting. */
++
++#include "libgomp.h"
++
++#include <stdlib.h>
++#include <unistd.h>
++#include <pthread.h>
++#include <pthread_np.h>
++
++static unsigned int affinity_counter;
++
++void
++gomp_init_affinity (void)
++{
++ cpuset_t cpuset, cpusetnew;
++ size_t idx, widx;
++ unsigned long cpus = 0;
++
++ if (pthread_getaffinity_np (pthread_self (), sizeof (cpuset), &cpuset))
++ {
++ gomp_error ("could not get CPU affinity set");
++ free (gomp_cpu_affinity);
++ gomp_cpu_affinity = NULL;
++ gomp_cpu_affinity_len = 0;
++ return;
++ }
++
++ CPU_ZERO (&cpusetnew);
++ if (gomp_cpu_affinity_len == 0)
++ {
++ unsigned long count = CPU_COUNT(&cpuset);
++ if (count >= 65536)
++ count = 65536;
++ gomp_cpu_affinity = malloc (count * sizeof (unsigned short));
++ if (gomp_cpu_affinity == NULL)
++ {
++ gomp_error ("not enough memory to store CPU affinity list");
++ return;
++ }
++ for (widx = idx = 0; widx < count && idx < 65536; idx++)
++ if (CPU_ISSET (idx, &cpuset))
++ {
++ cpus++;
++ gomp_cpu_affinity[widx++] = idx;
++ }
++ }
++ else
++ for (widx = idx = 0; idx < gomp_cpu_affinity_len; idx++)
++ if (gomp_cpu_affinity[idx] < CPU_SETSIZE
++ && CPU_ISSET (gomp_cpu_affinity[idx], &cpuset))
++ {
++ if (! CPU_ISSET (gomp_cpu_affinity[idx], &cpusetnew))
++ {
++ cpus++;
++ CPU_SET (gomp_cpu_affinity[idx], &cpusetnew);
++ }
++ gomp_cpu_affinity[widx++] = gomp_cpu_affinity[idx];
++ }
++
++ if (widx == 0)
++ {
++ gomp_error ("no CPUs left for affinity setting");
++ free (gomp_cpu_affinity);
++ gomp_cpu_affinity = NULL;
++ gomp_cpu_affinity_len = 0;
++ return;
++ }
++
++ gomp_cpu_affinity_len = widx;
++ if (cpus < gomp_available_cpus)
++ gomp_available_cpus = cpus;
++ CPU_ZERO (&cpuset);
++ CPU_SET (gomp_cpu_affinity[0], &cpuset);
++ pthread_setaffinity_np (pthread_self (), sizeof (cpuset), &cpuset);
++ affinity_counter = 1;
++}
++
++void
++gomp_init_thread_affinity (pthread_attr_t *attr)
++{
++ unsigned int cpu;
++ cpuset_t cpuset;
++
++ cpu = __atomic_fetch_add (&affinity_counter, 1, MEMMODEL_RELAXED);
++ cpu %= gomp_cpu_affinity_len;
++ CPU_ZERO (&cpuset);
++ CPU_SET (gomp_cpu_affinity[cpu], &cpuset);
++ pthread_attr_setaffinity_np (attr, sizeof (cpuset_t), &cpuset);
++}
diff --git a/lang/gcc48/files/patch-libgomp-posix-affinity b/lang/gcc48/files/patch-libgomp-posix-affinity
new file mode 100644
index 000000000000..c4ab742f061b
--- /dev/null
+++ b/lang/gcc48/files/patch-libgomp-posix-affinity
@@ -0,0 +1,18 @@
+--- libgomp/config/posix/affinity.c.orig 2015-04-26 05:29:27.925344000 -0700
++++ libgomp/config/posix/affinity.c 2015-04-26 05:29:44.449277000 -0700
+@@ -26,6 +26,10 @@
+
+ #include "libgomp.h"
+
++#ifdef __FreeBSD__
++#include "../bsd/freebsd_affinity.c"
++#else
++
+ void
+ gomp_init_affinity (void)
+ {
+@@ -36,3 +40,4 @@
+ {
+ (void) attr;
+ }
++#endif