From c66e8fa392161a414a07ad65a9f14b0b3ba02516 Mon Sep 17 00:00:00 2001 From: Erik Lindahl Date: Wed, 5 Aug 2015 17:48:44 +0200 Subject: [PATCH] Prevent AMD OpenCL on OS X prior to 10.10.4 OS X release 10.9.x has been confirmed to produce invalid OpenCL kernels for AMD (but correct for NVIDIA), and we have tested that it is fixed in 10.10.4. The fix might actually have appeared already in 10.10.3, but it's not worth tracking down the exact point since 10.10.5 is already out. This change will issue a CMake warning when compiling GROMACS on earlier OS X releases, and at runtime we check the version again and mark AMD GPUs as incompatible. Also fixed docs about the length of time JIT compilation takes on AMD. Refs #1783 Change-Id: I0202faea60c39daae6621d2bb9ba828aab5532a0 --- cmake/gmxManageOpenCL.cmake | 5 ++ docs/install-guide/index.rst | 2 + docs/user-guide/mdrun-performance.rst | 9 ++-- .../gmxlib/gpu_utils/gpu_utils_ocl.cpp | 46 +++++++++++++++++-- 4 files changed, 51 insertions(+), 11 deletions(-) diff --git a/cmake/gmxManageOpenCL.cmake b/cmake/gmxManageOpenCL.cmake index 721defc8df..5976b16004 100644 --- a/cmake/gmxManageOpenCL.cmake +++ b/cmake/gmxManageOpenCL.cmake @@ -57,6 +57,11 @@ if (UNIX) set(OPENCL_DEFINITIONS ${OPENCL_DEFINITIONS} " -Wno-comment") endif() +# Yes Virginia, Darwin kernel version 14.4 corresponds to OS X 10.4. +if(APPLE AND ${CMAKE_SYSTEM_VERSION} VERSION_LESS "14.4") + message(WARNING "OS X prior to version 10.10.4 produces incorrect AMD OpenCL code at runtime. You will not be able to use AMD GPUs on this host unless you upgrade your operating system."); +endif() + add_definitions(${OPENCL_DEFINITIONS}) include_directories(${OPENCL_INCLUDE_DIRS}) diff --git a/docs/install-guide/index.rst b/docs/install-guide/index.rst index 5f1033a8cb..9596008091 100644 --- a/docs/install-guide/index.rst +++ b/docs/install-guide/index.rst @@ -630,6 +630,8 @@ do so anyway, because NVIDIA OpenCL support is part of the CUDA package, a C++ compiler supported by your CUDA installation is required. +On Mac OS, an AMD GPU can be used only with OS version 10.10.4 and +higher; earlier OS versions are known to run incorrectly. Static linking ^^^^^^^^^^^^^^ diff --git a/docs/user-guide/mdrun-performance.rst b/docs/user-guide/mdrun-performance.rst index 4f05916458..6a3bd12b31 100644 --- a/docs/user-guide/mdrun-performance.rst +++ b/docs/user-guide/mdrun-performance.rst @@ -537,12 +537,9 @@ The following devices are known to work correctly: - NVIDIA: GeForce GTX 660M, GeForce GTX 660Ti, GeForce GTX 750Ti, GeForce GTX 780, GTX Titan -Building an OpenCL program can take a significant amount of -time. NVIDIA implements a mechanism to cache the result of the -build. As a consequence, only the first run will take longer (because -of the kernel builds), and the following runs will be very fast. AMD -drivers, on the other hand, implement no caching and the initial phase -of running an OpenCL program can be very slow. This is not normally a +Building the OpenCL program can take a few seconds when :ref:`gmx +mdrun` starts up, because the kernels that run on the +GPU can only be compiled at run time. This is not normally a problem for long production MD, but you might prefer to do some kinds of work on just the CPU (e.g. see ``-nb`` above). diff --git a/src/gromacs/gmxlib/gpu_utils/gpu_utils_ocl.cpp b/src/gromacs/gmxlib/gpu_utils/gpu_utils_ocl.cpp index d1e7c270cc..c3c5cbb86a 100644 --- a/src/gromacs/gmxlib/gpu_utils/gpu_utils_ocl.cpp +++ b/src/gromacs/gmxlib/gpu_utils/gpu_utils_ocl.cpp @@ -46,6 +46,9 @@ #include #include #include +#if __APPLE__ +# include +#endif #include @@ -81,6 +84,36 @@ static bool is_compatible_gpu(int stat) return (stat == egpuCompatible); } +/*! \brief Return true if executing on OS X earlier than 10.10.4 + * + * Uses the BSD sysctl() interfaces to extract the kernel version. + * + * \return true if version is 14.4 or later (= OS X version 10.10.4), + * otherwise false. + */ +static bool +runningOnWorkingOSXVersionForAmd() +{ +#ifdef __APPLE__ + int mib[2]; + char kernelVersion[256]; + size_t len = sizeof(kernelVersion); + + mib[0] = CTL_KERN; + mib[1] = KERN_OSRELEASE; + + sysctl(mib, sizeof(mib)/sizeof(mib[0]), kernelVersion, &len, NULL, 0); + + int major = strtod(kernelVersion, NULL); + int minor = strtod(strchr(kernelVersion, '.')+1, NULL); + + // Kernel 14.4 corresponds to OS X 10.10.4 + return (major > 14 || (major == 14 && minor >= 4)); +#else + return false; +#endif +} + /*! \brief Returns true if the gpu characterized by the device properties is * supported by the native gpu acceleration. * \returns true if the GPU properties passed indicate a compatible @@ -89,15 +122,18 @@ static bool is_compatible_gpu(int stat) static int is_gmx_supported_gpu_id(struct gmx_device_info_t *ocl_gpu_device) { /* Only AMD and NVIDIA GPUs are supported for now */ - if ((OCL_VENDOR_NVIDIA == ocl_gpu_device->vendor_e) || - (OCL_VENDOR_AMD == ocl_gpu_device->vendor_e)) + switch (ocl_gpu_device->vendor_e) { - return egpuCompatible; + case OCL_VENDOR_NVIDIA: + return egpuCompatible; + case OCL_VENDOR_AMD: + return runningOnWorkingOSXVersionForAmd() ? egpuCompatible : egpuIncompatible; + default: + return egpuIncompatible; } - - return egpuIncompatible; } + /*! \brief Returns an ocl_vendor_id_t value corresponding to the input OpenCL vendor name. * * \param[in] vendor_name String with OpenCL vendor name.