summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRobert Maynard <robert.maynard@kitware.com>2019-05-09 13:13:39 (GMT)
committerRobert Maynard <robert.maynard@kitware.com>2019-05-21 15:40:07 (GMT)
commit81b4d10d8f421242f9989ff0c2d37a12be66f405 (patch)
tree74ee6499eb43e48f18dd41ff0b0b1bdd809768cc
parent3205c7c950d5b90d47ce1c5c58073e511339b78c (diff)
downloadCMake-81b4d10d8f421242f9989ff0c2d37a12be66f405.zip
CMake-81b4d10d8f421242f9989ff0c2d37a12be66f405.tar.gz
CMake-81b4d10d8f421242f9989ff0c2d37a12be66f405.tar.bz2
CUDA: More exhaustive checks to determine when to do device linking
Previously CMake used fairly naive logic to determine when to do device linking which caused unnecessary device linking to occur frequently. We now use a more exhaustive algorithm to determine when we have a need for device linking. Fixes: #19238
-rw-r--r--Source/cmLinkLineDeviceComputer.cxx97
-rw-r--r--Source/cmLinkLineDeviceComputer.h6
-rw-r--r--Source/cmMakefileExecutableTargetGenerator.cxx18
-rw-r--r--Source/cmMakefileLibraryTargetGenerator.cxx51
-rw-r--r--Source/cmNinjaNormalTargetGenerator.cxx30
-rw-r--r--Source/cmVisualStudio10TargetGenerator.cxx18
-rwxr-xr-xbootstrap1
7 files changed, 113 insertions, 108 deletions
diff --git a/Source/cmLinkLineDeviceComputer.cxx b/Source/cmLinkLineDeviceComputer.cxx
index 72edba3..6cfe5bb 100644
--- a/Source/cmLinkLineDeviceComputer.cxx
+++ b/Source/cmLinkLineDeviceComputer.cxx
@@ -3,14 +3,20 @@
#include "cmLinkLineDeviceComputer.h"
+#include <algorithm>
#include <set>
#include <sstream>
#include <utility>
+#include <vector>
#include "cmAlgorithms.h"
#include "cmComputeLinkInformation.h"
#include "cmGeneratorTarget.h"
+#include "cmLocalGenerator.h"
+#include "cmStateDirectory.h"
+#include "cmStateSnapshot.h"
#include "cmStateTypes.h"
+#include "cmSystemTools.h"
class cmOutputConverter;
@@ -40,6 +46,27 @@ static bool cmLinkItemValidForDevice(std::string const& item)
cmHasLiteralPrefix(item, "--library"));
}
+bool cmLinkLineDeviceComputer::ComputeRequiresDeviceLinking(
+ cmComputeLinkInformation& cli)
+{
+ // Determine if this item might requires device linking.
+ // For this we only consider targets
+ typedef cmComputeLinkInformation::ItemVector ItemVector;
+ ItemVector const& items = cli.GetItems();
+ std::string config = cli.GetConfig();
+ for (auto const& item : items) {
+ if (item.Target &&
+ item.Target->GetType() == cmStateEnums::STATIC_LIBRARY) {
+ if ((!item.Target->GetPropertyAsBool("CUDA_RESOLVE_DEVICE_SYMBOLS")) &&
+ item.Target->GetPropertyAsBool("CUDA_SEPARABLE_COMPILATION")) {
+ // this dependency requires us to device link it
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
std::string cmLinkLineDeviceComputer::ComputeLinkLibraries(
cmComputeLinkInformation& cli, std::string const& stdLibString)
{
@@ -62,17 +89,12 @@ std::string cmLinkLineDeviceComputer::ComputeLinkLibraries(
}
if (item.Target) {
- bool skip = false;
- switch (item.Target->GetType()) {
- case cmStateEnums::MODULE_LIBRARY:
- case cmStateEnums::INTERFACE_LIBRARY:
- skip = true;
- break;
- case cmStateEnums::STATIC_LIBRARY:
- skip = item.Target->GetPropertyAsBool("CUDA_RESOLVE_DEVICE_SYMBOLS");
- break;
- default:
- break;
+ bool skip = true;
+ if (item.Target->GetType() == cmStateEnums::STATIC_LIBRARY) {
+ if ((!item.Target->GetPropertyAsBool("CUDA_RESOLVE_DEVICE_SYMBOLS")) &&
+ item.Target->GetPropertyAsBool("CUDA_SEPARABLE_COMPILATION")) {
+ skip = false;
+ }
}
if (skip) {
continue;
@@ -116,3 +138,56 @@ std::string cmLinkLineDeviceComputer::GetLinkerLanguage(cmGeneratorTarget*,
{
return "CUDA";
}
+
+bool requireDeviceLinking(cmGeneratorTarget& target, cmLocalGenerator& lg,
+ const std::string& config)
+{
+
+ if (target.GetType() == cmStateEnums::OBJECT_LIBRARY) {
+ return false;
+ }
+
+ if (const char* resolveDeviceSymbols =
+ target.GetProperty("CUDA_RESOLVE_DEVICE_SYMBOLS")) {
+ // If CUDA_RESOLVE_DEVICE_SYMBOLS has been explicitly set we need
+ // to honor the value no matter what it is.
+ return cmSystemTools::IsOn(resolveDeviceSymbols);
+ }
+
+ if (const char* separableCompilation =
+ target.GetProperty("CUDA_SEPARABLE_COMPILATION")) {
+ if (cmSystemTools::IsOn(separableCompilation)) {
+ bool doDeviceLinking = false;
+ switch (target.GetType()) {
+ case cmStateEnums::SHARED_LIBRARY:
+ case cmStateEnums::MODULE_LIBRARY:
+ case cmStateEnums::EXECUTABLE:
+ doDeviceLinking = true;
+ break;
+ default:
+ break;
+ }
+ return doDeviceLinking;
+ }
+ }
+
+ // Determine if we have any dependencies that require
+ // us to do a device link step
+ const std::string cuda_lang("CUDA");
+ cmGeneratorTarget::LinkClosure const* closure =
+ target.GetLinkClosure(config);
+
+ bool closureHasCUDA =
+ (std::find(closure->Languages.begin(), closure->Languages.end(),
+ cuda_lang) != closure->Languages.end());
+ if (closureHasCUDA) {
+ cmComputeLinkInformation* pcli = target.GetLinkInformation(config);
+ if (pcli) {
+ cmLinkLineDeviceComputer deviceLinkComputer(
+ &lg, lg.GetStateSnapshot().GetDirectory());
+ return deviceLinkComputer.ComputeRequiresDeviceLinking(*pcli);
+ }
+ return true;
+ }
+ return false;
+}
diff --git a/Source/cmLinkLineDeviceComputer.h b/Source/cmLinkLineDeviceComputer.h
index 26fc125..0ea5f69 100644
--- a/Source/cmLinkLineDeviceComputer.h
+++ b/Source/cmLinkLineDeviceComputer.h
@@ -12,6 +12,7 @@
class cmComputeLinkInformation;
class cmGeneratorTarget;
+class cmLocalGenerator;
class cmOutputConverter;
class cmStateDirectory;
@@ -26,6 +27,8 @@ public:
cmLinkLineDeviceComputer& operator=(cmLinkLineDeviceComputer const&) =
delete;
+ bool ComputeRequiresDeviceLinking(cmComputeLinkInformation& cli);
+
std::string ComputeLinkLibraries(cmComputeLinkInformation& cli,
std::string const& stdLibString) override;
@@ -33,4 +36,7 @@ public:
std::string const& config) override;
};
+bool requireDeviceLinking(cmGeneratorTarget& target, cmLocalGenerator& lg,
+ const std::string& config);
+
#endif
diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx
index beabf91..1113a2c 100644
--- a/Source/cmMakefileExecutableTargetGenerator.cxx
+++ b/Source/cmMakefileExecutableTargetGenerator.cxx
@@ -2,7 +2,6 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmMakefileExecutableTargetGenerator.h"
-#include <algorithm>
#include <memory> // IWYU pragma: keep
#include <set>
#include <sstream>
@@ -87,20 +86,9 @@ void cmMakefileExecutableTargetGenerator::WriteDeviceExecutableRule(
return;
}
- const std::string cuda_lang("CUDA");
- cmGeneratorTarget::LinkClosure const* closure =
- this->GeneratorTarget->GetLinkClosure(this->ConfigName);
-
- const bool hasCUDA =
- (std::find(closure->Languages.begin(), closure->Languages.end(),
- cuda_lang) != closure->Languages.end());
-
- bool doDeviceLinking = true;
- if (const char* resolveDeviceSymbols =
- this->GeneratorTarget->GetProperty("CUDA_RESOLVE_DEVICE_SYMBOLS")) {
- doDeviceLinking = cmSystemTools::IsOn(resolveDeviceSymbols);
- }
- if (!hasCUDA || !doDeviceLinking) {
+ bool requiresDeviceLinking = requireDeviceLinking(
+ *this->GeneratorTarget, *this->LocalGenerator, this->ConfigName);
+ if (!requiresDeviceLinking) {
return;
}
diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx
index f5d1fc9..d4d565d 100644
--- a/Source/cmMakefileLibraryTargetGenerator.cxx
+++ b/Source/cmMakefileLibraryTargetGenerator.cxx
@@ -2,7 +2,6 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmMakefileLibraryTargetGenerator.h"
-#include <algorithm>
#include <memory> // IWYU pragma: keep
#include <set>
#include <sstream>
@@ -124,20 +123,10 @@ void cmMakefileLibraryTargetGenerator::WriteObjectLibraryRules()
void cmMakefileLibraryTargetGenerator::WriteStaticLibraryRules()
{
- const std::string cuda_lang("CUDA");
- cmGeneratorTarget::LinkClosure const* closure =
- this->GeneratorTarget->GetLinkClosure(this->ConfigName);
-
- const bool hasCUDA =
- (std::find(closure->Languages.begin(), closure->Languages.end(),
- cuda_lang) != closure->Languages.end());
-
- bool doDeviceLinking = false;
- if (const char* resolveDeviceSymbols =
- this->GeneratorTarget->GetProperty("CUDA_RESOLVE_DEVICE_SYMBOLS")) {
- doDeviceLinking = cmSystemTools::IsOn(resolveDeviceSymbols);
- }
- if (hasCUDA && doDeviceLinking) {
+
+ bool requiresDeviceLinking = requireDeviceLinking(
+ *this->GeneratorTarget, *this->LocalGenerator, this->ConfigName);
+ if (requiresDeviceLinking) {
std::string linkRuleVar = "CMAKE_CUDA_DEVICE_LINK_LIBRARY";
this->WriteDeviceLibraryRules(linkRuleVar, false);
}
@@ -163,19 +152,9 @@ void cmMakefileLibraryTargetGenerator::WriteSharedLibraryRules(bool relink)
}
if (!relink) {
- const std::string cuda_lang("CUDA");
- cmGeneratorTarget::LinkClosure const* closure =
- this->GeneratorTarget->GetLinkClosure(this->ConfigName);
-
- const bool hasCUDA =
- (std::find(closure->Languages.begin(), closure->Languages.end(),
- cuda_lang) != closure->Languages.end());
- bool doDeviceLinking = true;
- if (const char* resolveDeviceSymbols =
- this->GeneratorTarget->GetProperty("CUDA_RESOLVE_DEVICE_SYMBOLS")) {
- doDeviceLinking = cmSystemTools::IsOn(resolveDeviceSymbols);
- }
- if (hasCUDA && doDeviceLinking) {
+ bool requiresDeviceLinking = requireDeviceLinking(
+ *this->GeneratorTarget, *this->LocalGenerator, this->ConfigName);
+ if (requiresDeviceLinking) {
std::string linkRuleVar = "CMAKE_CUDA_DEVICE_LINK_LIBRARY";
this->WriteDeviceLibraryRules(linkRuleVar, relink);
}
@@ -209,19 +188,9 @@ void cmMakefileLibraryTargetGenerator::WriteModuleLibraryRules(bool relink)
{
if (!relink) {
- const std::string cuda_lang("CUDA");
- cmGeneratorTarget::LinkClosure const* closure =
- this->GeneratorTarget->GetLinkClosure(this->ConfigName);
-
- const bool hasCUDA =
- (std::find(closure->Languages.begin(), closure->Languages.end(),
- cuda_lang) != closure->Languages.end());
- bool doDeviceLinking = true;
- if (const char* resolveDeviceSymbols =
- this->GeneratorTarget->GetProperty("CUDA_RESOLVE_DEVICE_SYMBOLS")) {
- doDeviceLinking = cmSystemTools::IsOn(resolveDeviceSymbols);
- }
- if (hasCUDA && doDeviceLinking) {
+ bool requiresDeviceLinking = requireDeviceLinking(
+ *this->GeneratorTarget, *this->LocalGenerator, this->ConfigName);
+ if (requiresDeviceLinking) {
std::string linkRuleVar = "CMAKE_CUDA_DEVICE_LINK_LIBRARY";
this->WriteDeviceLibraryRules(linkRuleVar, relink);
}
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index 4d13006..f8a13ce 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -18,6 +18,7 @@
#include "cmGeneratorTarget.h"
#include "cmGlobalNinjaGenerator.h"
#include "cmLinkLineComputer.h"
+#include "cmLinkLineDeviceComputer.h"
#include "cmLocalGenerator.h"
#include "cmLocalNinjaGenerator.h"
#include "cmMakefile.h"
@@ -571,32 +572,9 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement()
cmGeneratorTarget& genTarget = *this->GetGeneratorTarget();
- // determine if we need to do any device linking for this target
- const std::string cuda_lang("CUDA");
- cmGeneratorTarget::LinkClosure const* closure =
- genTarget.GetLinkClosure(this->GetConfigName());
-
- const bool hasCUDA =
- (std::find(closure->Languages.begin(), closure->Languages.end(),
- cuda_lang) != closure->Languages.end());
-
- bool doDeviceLinking = false;
- if (const char* resolveDeviceSymbols =
- genTarget.GetProperty("CUDA_RESOLVE_DEVICE_SYMBOLS")) {
- doDeviceLinking = cmSystemTools::IsOn(resolveDeviceSymbols);
- } else {
- switch (genTarget.GetType()) {
- case cmStateEnums::SHARED_LIBRARY:
- case cmStateEnums::MODULE_LIBRARY:
- case cmStateEnums::EXECUTABLE:
- doDeviceLinking = true;
- break;
- default:
- break;
- }
- }
-
- if (!(doDeviceLinking && hasCUDA)) {
+ bool requiresDeviceLinking = requireDeviceLinking(
+ *this->GeneratorTarget, *this->GetLocalGenerator(), this->ConfigName);
+ if (!requiresDeviceLinking) {
return;
}
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index c60706d..0685a41 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -10,6 +10,7 @@
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalVisualStudio10Generator.h"
+#include "cmLinkLineDeviceComputer.h"
#include "cmLocalVisualStudio10Generator.h"
#include "cmMakefile.h"
#include "cmSourceFile.h"
@@ -3007,21 +3008,8 @@ bool cmVisualStudio10TargetGenerator::ComputeCudaLinkOptions(
Options& cudaLinkOptions = *pOptions;
// Determine if we need to do a device link
- bool doDeviceLinking = false;
- if (const char* resolveDeviceSymbols =
- this->GeneratorTarget->GetProperty("CUDA_RESOLVE_DEVICE_SYMBOLS")) {
- doDeviceLinking = cmSystemTools::IsOn(resolveDeviceSymbols);
- } else {
- switch (this->GeneratorTarget->GetType()) {
- case cmStateEnums::SHARED_LIBRARY:
- case cmStateEnums::MODULE_LIBRARY:
- case cmStateEnums::EXECUTABLE:
- doDeviceLinking = true;
- break;
- default:
- break;
- }
- }
+ bool doDeviceLinking = requireDeviceLinking(
+ *this->GeneratorTarget, *this->LocalGenerator, configName);
cudaLinkOptions.AddFlag("PerformDeviceLink",
doDeviceLinking ? "true" : "false");
diff --git a/bootstrap b/bootstrap
index c5274ce..ce27ca6 100755
--- a/bootstrap
+++ b/bootstrap
@@ -359,6 +359,7 @@ CMAKE_CXX_SOURCES="\
cmLinkDirectoriesCommand \
cmLinkItem \
cmLinkLineComputer \
+ cmLinkLineDeviceComputer \
cmListCommand \
cmListFileCache \
cmLocalCommonGenerator \