From 122097be00609a525cc756a9fba707685c789710 Mon Sep 17 00:00:00 2001 From: Jason Lowe Date: Wed, 14 Apr 2021 13:09:23 -0500 Subject: [PATCH 1/3] Log plugin and cudf versions on startup Signed-off-by: Jason Lowe --- .../com/nvidia/spark/rapids/Plugin.scala | 117 ++++++++++-------- 1 file changed, 65 insertions(+), 52 deletions(-) diff --git a/sql-plugin/src/main/scala/com/nvidia/spark/rapids/Plugin.scala b/sql-plugin/src/main/scala/com/nvidia/spark/rapids/Plugin.scala index 2541918d22e..e724350e01c 100644 --- a/sql-plugin/src/main/scala/com/nvidia/spark/rapids/Plugin.scala +++ b/sql-plugin/src/main/scala/com/nvidia/spark/rapids/Plugin.scala @@ -38,6 +38,10 @@ import org.apache.spark.sql.internal.StaticSQLConf import org.apache.spark.sql.rapids.GpuShuffleEnv import org.apache.spark.sql.util.QueryExecutionListener +class PluginException(msg: String) extends RuntimeException(msg) + +case class CudfVersionMismatchException(errorMsg: String) extends PluginException(errorMsg) + case class ColumnarOverrideRules() extends ColumnarRule with Logging { val overrides: Rule[SparkPlan] = GpuOverrides() val overrideTransitions: Rule[SparkPlan] = new GpuTransitionOverrides() @@ -52,7 +56,9 @@ case class ColumnarOverrideRules() extends ColumnarRule with Logging { */ class SQLExecPlugin extends (SparkSessionExtensions => Unit) with Logging { override def apply(extensions: SparkSessionExtensions): Unit = { - logWarning("Installing extensions to enable rapids GPU SQL support." + + val pluginVersion = RapidsPluginUtils.getPluginVersion + val cudfVersion = RapidsPluginUtils.getClasspathCudfVersion + logWarning(s"RAPIDS Accelerator $pluginVersion using cudf $cudfVersion." + s" To disable GPU support set `${RapidsConf.SQL_ENABLED}` to false") extensions.injectColumnar(_ => ColumnarOverrideRules()) ShimLoader.getSparkShims.injectQueryStagePrepRule(extensions, _ => GpuQueryStagePrepOverrides()) @@ -66,8 +72,10 @@ object RapidsPluginUtils extends Logging { private val SERIALIZER_CONF_KEY = "spark.serializer" private val JAVA_SERIALIZER_NAME = classOf[JavaSerializer].getName private val KRYO_SERIALIZER_NAME = classOf[KryoSerializer].getName - private val KRYO_REGISRATOR_KEY = "spark.kryo.registrator" - private val KRYO_REGISRATOR_NAME = classOf[GpuKryoRegistrator].getName + private val KRYO_REGISTRATOR_KEY = "spark.kryo.registrator" + private val KRYO_REGISTRATOR_NAME = classOf[GpuKryoRegistrator].getName + private val CUDF_PROPS_FILENAME = "cudf-java-version-info.properties" + private val PLUGIN_PROPS_FILENAME = "rapids4spark-version-info.properties" def fixupConfigs(conf: SparkConf): Unit = { // First add in the SQL executor plugin because that is what we need at a minimum @@ -86,22 +94,54 @@ object RapidsPluginUtils extends Logging { val serializer = conf.get(SERIALIZER_CONF_KEY, JAVA_SERIALIZER_NAME) if (KRYO_SERIALIZER_NAME.equals(serializer)) { - if (conf.contains(KRYO_REGISRATOR_KEY)) { - if (!KRYO_REGISRATOR_NAME.equals(conf.get(KRYO_REGISRATOR_KEY)) ) { - logWarning("Rapids SQL Plugin when used with Kryo needs to register some " + - s"serializers using $KRYO_REGISRATOR_NAME. Please call it from your registrator " + - " to let the plugin work properly.") + if (conf.contains(KRYO_REGISTRATOR_KEY)) { + if (!KRYO_REGISTRATOR_NAME.equals(conf.get(KRYO_REGISTRATOR_KEY)) ) { + logWarning("The RAPIDS Accelerator when used with Kryo needs to register some " + + s"serializers using $KRYO_REGISTRATOR_NAME. Please call it from your registrator " + + " to let the plugin work properly.") } // else it is set and we are good to go } else { // We cannot set the kryo key here, it is not early enough to be picked up everywhere - throw new UnsupportedOperationException("The Rapids SQL Plugin when used with Kryo needs " + - s"to register some serializers. Please set the spark config $KRYO_REGISRATOR_KEY to " + - s"$KRYO_REGISRATOR_NAME or some operations may not work properly.") + throw new UnsupportedOperationException("The RAPIDS Accelerator when used with Kryo " + + "needs to register some serializers. Please set the spark config " + + s"$KRYO_REGISTRATOR_KEY to $KRYO_REGISTRATOR_NAME or some operations may not work " + + "properly.") } } else if (!JAVA_SERIALIZER_NAME.equals(serializer)) { throw new UnsupportedOperationException(s"$serializer is not a supported serializer for " + - s"the Rapids SQL Plugin. Please disable the rapids plugin or use a supported serializer " + - s"serializer ($JAVA_SERIALIZER_NAME, $KRYO_SERIALIZER_NAME).") + s"the RAPIDS Accelerator. Please disable the RAPIDS Accelerator or use a supported " + + s"serializer ($JAVA_SERIALIZER_NAME, $KRYO_SERIALIZER_NAME).") + } + } + + /** Gets the plugin version string from the plugin properties file in the classpath */ + def getPluginVersion: String = { + getVersionFromPropsFile(PLUGIN_PROPS_FILENAME) + } + + /** Gets the cudf version string from the cudf properties file in the classpath*/ + def getClasspathCudfVersion: String = { + getVersionFromPropsFile(CUDF_PROPS_FILENAME) + } + + /** Loads the plugin properties file in the classpath */ + def getPluginProps: Properties = loadProps(PLUGIN_PROPS_FILENAME) + + private def loadProps(resourceName: String): Properties = { + val classLoader = RapidsPluginUtils.getClass.getClassLoader + val resource = classLoader.getResourceAsStream(resourceName) + if (resource == null) { + throw new PluginException(s"Could not find properties file $resourceName in the classpath") + } + val props = new Properties + props.load(resource) + props + } + + private def getVersionFromPropsFile(resourceName: String): String = { + val props = loadProps(resourceName) + Option(props.get("version")).map(_.toString).getOrElse { + throw new PluginException(s"Property name `version` not found in $resourceName file") } } } @@ -188,53 +228,26 @@ class RapidsExecutorPlugin extends ExecutorPlugin with Logging { private def checkCudfVersion(conf: RapidsConf): Unit = { try { - val cudfPropertiesFileName = "cudf-java-version-info.properties" - val pluginPropertiesFileName = "rapids4spark-version-info.properties" - - val props = new Properties - val classLoader = classOf[RapidsExecutorPlugin].getClassLoader - val cudfProperties = classLoader.getResourceAsStream(cudfPropertiesFileName) - if (cudfProperties == null) { - throw CudfVersionMismatchException(s"Could not find properties file " + - s"$cudfPropertiesFileName in the cudf jar. Cannot verify cudf version compatibility " + - s"with RAPIDS Accelerator version.") - } - props.load(cudfProperties) - - val classpathCudfVersion = props.get("version") - if (classpathCudfVersion == null) { - throw CudfVersionMismatchException(s"Property name `version` not found in " + - s"$cudfPropertiesFileName file.") - } - val cudfVersion = classpathCudfVersion.toString - - val pluginResource = classLoader.getResourceAsStream(pluginPropertiesFileName) - if (pluginResource == null) { - throw CudfVersionMismatchException(s"Could not find properties file " + - s"$pluginPropertiesFileName in the RAPIDS Accelerator jar. Cannot verify cudf " + - s"version compatibility with RAPIDS Accelerator version.") - } - props.load(pluginResource) - - val pluginCudfVersion = props.get("cudf_version") - if (pluginCudfVersion == null) { - throw CudfVersionMismatchException(s"Property name `cudf_version` not found in" + - s" $pluginPropertiesFileName file.") + val cudfVersion = RapidsPluginUtils.getClasspathCudfVersion + val pluginProps = RapidsPluginUtils.getPluginProps + val expectedCudfVersion = Option(pluginProps.get("cudf_version")).map(_.toString).getOrElse { + throw CudfVersionMismatchException("Could not find cudf version in plugin properties file") } - val expectedCudfVersion = pluginCudfVersion.toString // compare cudf version in the classpath with the cudf version expected by plugin if (!RapidsExecutorPlugin.cudfVersionSatisfied(expectedCudfVersion, cudfVersion)) { - throw CudfVersionMismatchException(s"Cudf version in the classpath is different. " + - s"Found $cudfVersion, RAPIDS Accelerator expects $expectedCudfVersion") + throw CudfVersionMismatchException(s"Found cudf version $cudfVersion, RAPIDS Accelerator " + + s"expects $expectedCudfVersion") } + val pluginVersion = Option(pluginProps.get("version")).map(_.toString).getOrElse { + throw new PluginException("No `version` property in plugin properties file") + } + logInfo(s"RAPIDS Accelerator $pluginVersion using cudf $cudfVersion") } catch { - case x: CudfVersionMismatchException if conf.cudfVersionOverride => - logWarning(s"${x.errorMsg}") + case x: PluginException if conf.cudfVersionOverride => + logWarning(s"${x.getMessage}") } } - case class CudfVersionMismatchException(errorMsg: String) extends RuntimeException(errorMsg) - override def shutdown(): Unit = { GpuSemaphore.shutdown() PythonWorkerSemaphore.shutdown() From 3819d5ce7978451ee42180c865c37c429e068420 Mon Sep 17 00:00:00 2001 From: Jason Lowe Date: Wed, 14 Apr 2021 17:25:12 -0500 Subject: [PATCH 2/3] Log full build properties at INFO level Signed-off-by: Jason Lowe --- docs/FAQ.md | 15 +++++ .../com/nvidia/spark/rapids/Plugin.scala | 57 ++++++++----------- 2 files changed, 38 insertions(+), 34 deletions(-) diff --git a/docs/FAQ.md b/docs/FAQ.md index 3e4e440b22b..e31e50be301 100644 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -34,6 +34,21 @@ CUDA 10.1, 10.2 and 11.0 are currently supported, but you need to download the c corresponds to the version you are using. Please look [here](download.md) for download links for the latest release. +### How can I check if the RAPIDS Accelerator is installed and which version is running? + +On startup the RAPIDS Accelerator will log a warning message on the Spark driver showing the +version with a message that looks something like this: +``` +21/04/14 22:14:55 WARN SQLExecPlugin: RAPIDS Accelerator 0.5.0 using cudf 0.19. To disable GPU support set `spark.rapids.sql.enabled` to false +``` + +The full RAPIDS Accelerator and cudf build properties are logged at `INFO` level in the +Spark driver and executor logs with messages that are similar to the following: +``` +21/04/14 17:20:20 INFO RapidsExecutorPlugin: RAPIDS Accelerator build: {version=0.5.0-SNAPSHOT, user=jlowe, url=, date=2021-04-14T22:12:14Z, revision=79a5cf8acd615587b2c7835072b0d8b0d4604f8b, cudf_version=0.19-SNAPSHOT, branch=branch-0.5} +21/04/14 17:20:20 INFO RapidsExecutorPlugin: cudf build: {version=0.19-SNAPSHOT, user=, date=2021-04-13T08:42:40Z, revision=a5d2407b93de444a6a7faf9db4b7dbf4ecbfe9ed, branch=HEAD} +``` + ### What is the right hardware setup to run GPU accelerated Spark? Reference architectures should be available around Q1 2021. diff --git a/sql-plugin/src/main/scala/com/nvidia/spark/rapids/Plugin.scala b/sql-plugin/src/main/scala/com/nvidia/spark/rapids/Plugin.scala index e724350e01c..3a2d9715bdb 100644 --- a/sql-plugin/src/main/scala/com/nvidia/spark/rapids/Plugin.scala +++ b/sql-plugin/src/main/scala/com/nvidia/spark/rapids/Plugin.scala @@ -56,8 +56,12 @@ case class ColumnarOverrideRules() extends ColumnarRule with Logging { */ class SQLExecPlugin extends (SparkSessionExtensions => Unit) with Logging { override def apply(extensions: SparkSessionExtensions): Unit = { - val pluginVersion = RapidsPluginUtils.getPluginVersion - val cudfVersion = RapidsPluginUtils.getClasspathCudfVersion + val pluginProps = RapidsPluginUtils.loadProps(RapidsPluginUtils.PLUGIN_PROPS_FILENAME) + logInfo(s"RAPIDS Accelerator build: $pluginProps") + val cudfProps = RapidsPluginUtils.loadProps(RapidsPluginUtils.CUDF_PROPS_FILENAME) + logInfo(s"cudf build: $pluginProps") + val pluginVersion = pluginProps.getProperty("version", "UNKNOWN") + val cudfVersion = cudfProps.getProperty("version", "UNKNOWN") logWarning(s"RAPIDS Accelerator $pluginVersion using cudf $cudfVersion." + s" To disable GPU support set `${RapidsConf.SQL_ENABLED}` to false") extensions.injectColumnar(_ => ColumnarOverrideRules()) @@ -66,6 +70,9 @@ class SQLExecPlugin extends (SparkSessionExtensions => Unit) with Logging { } object RapidsPluginUtils extends Logging { + val CUDF_PROPS_FILENAME = "cudf-java-version-info.properties" + val PLUGIN_PROPS_FILENAME = "rapids4spark-version-info.properties" + private val SQL_PLUGIN_NAME = classOf[SQLExecPlugin].getName private val UDF_PLUGIN_NAME = "com.nvidia.spark.udf.Plugin" private val SQL_PLUGIN_CONF_KEY = StaticSQLConf.SPARK_SESSION_EXTENSIONS.key @@ -74,8 +81,6 @@ object RapidsPluginUtils extends Logging { private val KRYO_SERIALIZER_NAME = classOf[KryoSerializer].getName private val KRYO_REGISTRATOR_KEY = "spark.kryo.registrator" private val KRYO_REGISTRATOR_NAME = classOf[GpuKryoRegistrator].getName - private val CUDF_PROPS_FILENAME = "cudf-java-version-info.properties" - private val PLUGIN_PROPS_FILENAME = "rapids4spark-version-info.properties" def fixupConfigs(conf: SparkConf): Unit = { // First add in the SQL executor plugin because that is what we need at a minimum @@ -114,20 +119,7 @@ object RapidsPluginUtils extends Logging { } } - /** Gets the plugin version string from the plugin properties file in the classpath */ - def getPluginVersion: String = { - getVersionFromPropsFile(PLUGIN_PROPS_FILENAME) - } - - /** Gets the cudf version string from the cudf properties file in the classpath*/ - def getClasspathCudfVersion: String = { - getVersionFromPropsFile(CUDF_PROPS_FILENAME) - } - - /** Loads the plugin properties file in the classpath */ - def getPluginProps: Properties = loadProps(PLUGIN_PROPS_FILENAME) - - private def loadProps(resourceName: String): Properties = { + def loadProps(resourceName: String): Properties = { val classLoader = RapidsPluginUtils.getClass.getClassLoader val resource = classLoader.getResourceAsStream(resourceName) if (resource == null) { @@ -137,13 +129,6 @@ object RapidsPluginUtils extends Logging { props.load(resource) props } - - private def getVersionFromPropsFile(resourceName: String): String = { - val props = loadProps(resourceName) - Option(props.get("version")).map(_.toString).getOrElse { - throw new PluginException(s"Property name `version` not found in $resourceName file") - } - } } /** @@ -228,23 +213,27 @@ class RapidsExecutorPlugin extends ExecutorPlugin with Logging { private def checkCudfVersion(conf: RapidsConf): Unit = { try { - val cudfVersion = RapidsPluginUtils.getClasspathCudfVersion - val pluginProps = RapidsPluginUtils.getPluginProps - val expectedCudfVersion = Option(pluginProps.get("cudf_version")).map(_.toString).getOrElse { - throw CudfVersionMismatchException("Could not find cudf version in plugin properties file") + val pluginProps = RapidsPluginUtils.loadProps(RapidsPluginUtils.PLUGIN_PROPS_FILENAME) + logInfo(s"RAPIDS Accelerator build: $pluginProps") + val expectedCudfVersion = Option(pluginProps.getProperty("cudf_version")).getOrElse { + throw CudfVersionMismatchException("Could not find cudf version in " + + RapidsPluginUtils.PLUGIN_PROPS_FILENAME) + } + val cudfProps = RapidsPluginUtils.loadProps(RapidsPluginUtils.CUDF_PROPS_FILENAME) + logInfo(s"cudf build: $cudfProps") + val cudfVersion = Option(cudfProps.getProperty("version")).getOrElse { + throw CudfVersionMismatchException("Could not find cudf version in " + + RapidsPluginUtils.CUDF_PROPS_FILENAME) } // compare cudf version in the classpath with the cudf version expected by plugin if (!RapidsExecutorPlugin.cudfVersionSatisfied(expectedCudfVersion, cudfVersion)) { throw CudfVersionMismatchException(s"Found cudf version $cudfVersion, RAPIDS Accelerator " + s"expects $expectedCudfVersion") } - val pluginVersion = Option(pluginProps.get("version")).map(_.toString).getOrElse { - throw new PluginException("No `version` property in plugin properties file") - } - logInfo(s"RAPIDS Accelerator $pluginVersion using cudf $cudfVersion") } catch { case x: PluginException if conf.cudfVersionOverride => - logWarning(s"${x.getMessage}") + logWarning(s"Ignoring error due to ${RapidsConf.CUDF_VERSION_OVERRIDE.key}=true: " + + s"${x.getMessage}") } } From 074928beb5c942bf0288bb2b168a4d8f345c60dc Mon Sep 17 00:00:00 2001 From: Jason Lowe Date: Wed, 14 Apr 2021 17:55:30 -0500 Subject: [PATCH 3/3] Fix copy-paste error --- sql-plugin/src/main/scala/com/nvidia/spark/rapids/Plugin.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql-plugin/src/main/scala/com/nvidia/spark/rapids/Plugin.scala b/sql-plugin/src/main/scala/com/nvidia/spark/rapids/Plugin.scala index 3a2d9715bdb..bf6e695a726 100644 --- a/sql-plugin/src/main/scala/com/nvidia/spark/rapids/Plugin.scala +++ b/sql-plugin/src/main/scala/com/nvidia/spark/rapids/Plugin.scala @@ -59,7 +59,7 @@ class SQLExecPlugin extends (SparkSessionExtensions => Unit) with Logging { val pluginProps = RapidsPluginUtils.loadProps(RapidsPluginUtils.PLUGIN_PROPS_FILENAME) logInfo(s"RAPIDS Accelerator build: $pluginProps") val cudfProps = RapidsPluginUtils.loadProps(RapidsPluginUtils.CUDF_PROPS_FILENAME) - logInfo(s"cudf build: $pluginProps") + logInfo(s"cudf build: $cudfProps") val pluginVersion = pluginProps.getProperty("version", "UNKNOWN") val cudfVersion = cudfProps.getProperty("version", "UNKNOWN") logWarning(s"RAPIDS Accelerator $pluginVersion using cudf $cudfVersion." +