mirror of
https://github.com/Kitware/CMake.git
synced 2025-10-15 03:48:02 +08:00
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
This commit is contained in:
@@ -3,14 +3,20 @@
|
|||||||
|
|
||||||
#include "cmLinkLineDeviceComputer.h"
|
#include "cmLinkLineDeviceComputer.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "cmAlgorithms.h"
|
#include "cmAlgorithms.h"
|
||||||
#include "cmComputeLinkInformation.h"
|
#include "cmComputeLinkInformation.h"
|
||||||
#include "cmGeneratorTarget.h"
|
#include "cmGeneratorTarget.h"
|
||||||
|
#include "cmLocalGenerator.h"
|
||||||
|
#include "cmStateDirectory.h"
|
||||||
|
#include "cmStateSnapshot.h"
|
||||||
#include "cmStateTypes.h"
|
#include "cmStateTypes.h"
|
||||||
|
#include "cmSystemTools.h"
|
||||||
|
|
||||||
class cmOutputConverter;
|
class cmOutputConverter;
|
||||||
|
|
||||||
@@ -40,6 +46,27 @@ static bool cmLinkItemValidForDevice(std::string const& item)
|
|||||||
cmHasLiteralPrefix(item, "--library"));
|
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(
|
std::string cmLinkLineDeviceComputer::ComputeLinkLibraries(
|
||||||
cmComputeLinkInformation& cli, std::string const& stdLibString)
|
cmComputeLinkInformation& cli, std::string const& stdLibString)
|
||||||
{
|
{
|
||||||
@@ -62,17 +89,12 @@ std::string cmLinkLineDeviceComputer::ComputeLinkLibraries(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (item.Target) {
|
if (item.Target) {
|
||||||
bool skip = false;
|
bool skip = true;
|
||||||
switch (item.Target->GetType()) {
|
if (item.Target->GetType() == cmStateEnums::STATIC_LIBRARY) {
|
||||||
case cmStateEnums::MODULE_LIBRARY:
|
if ((!item.Target->GetPropertyAsBool("CUDA_RESOLVE_DEVICE_SYMBOLS")) &&
|
||||||
case cmStateEnums::INTERFACE_LIBRARY:
|
item.Target->GetPropertyAsBool("CUDA_SEPARABLE_COMPILATION")) {
|
||||||
skip = true;
|
skip = false;
|
||||||
break;
|
}
|
||||||
case cmStateEnums::STATIC_LIBRARY:
|
|
||||||
skip = item.Target->GetPropertyAsBool("CUDA_RESOLVE_DEVICE_SYMBOLS");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
if (skip) {
|
if (skip) {
|
||||||
continue;
|
continue;
|
||||||
@@ -116,3 +138,56 @@ std::string cmLinkLineDeviceComputer::GetLinkerLanguage(cmGeneratorTarget*,
|
|||||||
{
|
{
|
||||||
return "CUDA";
|
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;
|
||||||
|
}
|
||||||
|
@@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
class cmComputeLinkInformation;
|
class cmComputeLinkInformation;
|
||||||
class cmGeneratorTarget;
|
class cmGeneratorTarget;
|
||||||
|
class cmLocalGenerator;
|
||||||
class cmOutputConverter;
|
class cmOutputConverter;
|
||||||
class cmStateDirectory;
|
class cmStateDirectory;
|
||||||
|
|
||||||
@@ -26,6 +27,8 @@ public:
|
|||||||
cmLinkLineDeviceComputer& operator=(cmLinkLineDeviceComputer const&) =
|
cmLinkLineDeviceComputer& operator=(cmLinkLineDeviceComputer const&) =
|
||||||
delete;
|
delete;
|
||||||
|
|
||||||
|
bool ComputeRequiresDeviceLinking(cmComputeLinkInformation& cli);
|
||||||
|
|
||||||
std::string ComputeLinkLibraries(cmComputeLinkInformation& cli,
|
std::string ComputeLinkLibraries(cmComputeLinkInformation& cli,
|
||||||
std::string const& stdLibString) override;
|
std::string const& stdLibString) override;
|
||||||
|
|
||||||
@@ -33,4 +36,7 @@ public:
|
|||||||
std::string const& config) override;
|
std::string const& config) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bool requireDeviceLinking(cmGeneratorTarget& target, cmLocalGenerator& lg,
|
||||||
|
const std::string& config);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -2,7 +2,6 @@
|
|||||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||||
#include "cmMakefileExecutableTargetGenerator.h"
|
#include "cmMakefileExecutableTargetGenerator.h"
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <memory> // IWYU pragma: keep
|
#include <memory> // IWYU pragma: keep
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
@@ -87,20 +86,9 @@ void cmMakefileExecutableTargetGenerator::WriteDeviceExecutableRule(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string cuda_lang("CUDA");
|
bool requiresDeviceLinking = requireDeviceLinking(
|
||||||
cmGeneratorTarget::LinkClosure const* closure =
|
*this->GeneratorTarget, *this->LocalGenerator, this->ConfigName);
|
||||||
this->GeneratorTarget->GetLinkClosure(this->ConfigName);
|
if (!requiresDeviceLinking) {
|
||||||
|
|
||||||
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) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -2,7 +2,6 @@
|
|||||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||||
#include "cmMakefileLibraryTargetGenerator.h"
|
#include "cmMakefileLibraryTargetGenerator.h"
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <memory> // IWYU pragma: keep
|
#include <memory> // IWYU pragma: keep
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
@@ -124,20 +123,10 @@ void cmMakefileLibraryTargetGenerator::WriteObjectLibraryRules()
|
|||||||
|
|
||||||
void cmMakefileLibraryTargetGenerator::WriteStaticLibraryRules()
|
void cmMakefileLibraryTargetGenerator::WriteStaticLibraryRules()
|
||||||
{
|
{
|
||||||
const std::string cuda_lang("CUDA");
|
|
||||||
cmGeneratorTarget::LinkClosure const* closure =
|
|
||||||
this->GeneratorTarget->GetLinkClosure(this->ConfigName);
|
|
||||||
|
|
||||||
const bool hasCUDA =
|
bool requiresDeviceLinking = requireDeviceLinking(
|
||||||
(std::find(closure->Languages.begin(), closure->Languages.end(),
|
*this->GeneratorTarget, *this->LocalGenerator, this->ConfigName);
|
||||||
cuda_lang) != closure->Languages.end());
|
if (requiresDeviceLinking) {
|
||||||
|
|
||||||
bool doDeviceLinking = false;
|
|
||||||
if (const char* resolveDeviceSymbols =
|
|
||||||
this->GeneratorTarget->GetProperty("CUDA_RESOLVE_DEVICE_SYMBOLS")) {
|
|
||||||
doDeviceLinking = cmSystemTools::IsOn(resolveDeviceSymbols);
|
|
||||||
}
|
|
||||||
if (hasCUDA && doDeviceLinking) {
|
|
||||||
std::string linkRuleVar = "CMAKE_CUDA_DEVICE_LINK_LIBRARY";
|
std::string linkRuleVar = "CMAKE_CUDA_DEVICE_LINK_LIBRARY";
|
||||||
this->WriteDeviceLibraryRules(linkRuleVar, false);
|
this->WriteDeviceLibraryRules(linkRuleVar, false);
|
||||||
}
|
}
|
||||||
@@ -163,19 +152,9 @@ void cmMakefileLibraryTargetGenerator::WriteSharedLibraryRules(bool relink)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!relink) {
|
if (!relink) {
|
||||||
const std::string cuda_lang("CUDA");
|
bool requiresDeviceLinking = requireDeviceLinking(
|
||||||
cmGeneratorTarget::LinkClosure const* closure =
|
*this->GeneratorTarget, *this->LocalGenerator, this->ConfigName);
|
||||||
this->GeneratorTarget->GetLinkClosure(this->ConfigName);
|
if (requiresDeviceLinking) {
|
||||||
|
|
||||||
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) {
|
|
||||||
std::string linkRuleVar = "CMAKE_CUDA_DEVICE_LINK_LIBRARY";
|
std::string linkRuleVar = "CMAKE_CUDA_DEVICE_LINK_LIBRARY";
|
||||||
this->WriteDeviceLibraryRules(linkRuleVar, relink);
|
this->WriteDeviceLibraryRules(linkRuleVar, relink);
|
||||||
}
|
}
|
||||||
@@ -209,19 +188,9 @@ void cmMakefileLibraryTargetGenerator::WriteModuleLibraryRules(bool relink)
|
|||||||
{
|
{
|
||||||
|
|
||||||
if (!relink) {
|
if (!relink) {
|
||||||
const std::string cuda_lang("CUDA");
|
bool requiresDeviceLinking = requireDeviceLinking(
|
||||||
cmGeneratorTarget::LinkClosure const* closure =
|
*this->GeneratorTarget, *this->LocalGenerator, this->ConfigName);
|
||||||
this->GeneratorTarget->GetLinkClosure(this->ConfigName);
|
if (requiresDeviceLinking) {
|
||||||
|
|
||||||
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) {
|
|
||||||
std::string linkRuleVar = "CMAKE_CUDA_DEVICE_LINK_LIBRARY";
|
std::string linkRuleVar = "CMAKE_CUDA_DEVICE_LINK_LIBRARY";
|
||||||
this->WriteDeviceLibraryRules(linkRuleVar, relink);
|
this->WriteDeviceLibraryRules(linkRuleVar, relink);
|
||||||
}
|
}
|
||||||
|
@@ -18,6 +18,7 @@
|
|||||||
#include "cmGeneratorTarget.h"
|
#include "cmGeneratorTarget.h"
|
||||||
#include "cmGlobalNinjaGenerator.h"
|
#include "cmGlobalNinjaGenerator.h"
|
||||||
#include "cmLinkLineComputer.h"
|
#include "cmLinkLineComputer.h"
|
||||||
|
#include "cmLinkLineDeviceComputer.h"
|
||||||
#include "cmLocalGenerator.h"
|
#include "cmLocalGenerator.h"
|
||||||
#include "cmLocalNinjaGenerator.h"
|
#include "cmLocalNinjaGenerator.h"
|
||||||
#include "cmMakefile.h"
|
#include "cmMakefile.h"
|
||||||
@@ -571,32 +572,9 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement()
|
|||||||
|
|
||||||
cmGeneratorTarget& genTarget = *this->GetGeneratorTarget();
|
cmGeneratorTarget& genTarget = *this->GetGeneratorTarget();
|
||||||
|
|
||||||
// determine if we need to do any device linking for this target
|
bool requiresDeviceLinking = requireDeviceLinking(
|
||||||
const std::string cuda_lang("CUDA");
|
*this->GeneratorTarget, *this->GetLocalGenerator(), this->ConfigName);
|
||||||
cmGeneratorTarget::LinkClosure const* closure =
|
if (!requiresDeviceLinking) {
|
||||||
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)) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -10,6 +10,7 @@
|
|||||||
#include "cmGeneratorExpression.h"
|
#include "cmGeneratorExpression.h"
|
||||||
#include "cmGeneratorTarget.h"
|
#include "cmGeneratorTarget.h"
|
||||||
#include "cmGlobalVisualStudio10Generator.h"
|
#include "cmGlobalVisualStudio10Generator.h"
|
||||||
|
#include "cmLinkLineDeviceComputer.h"
|
||||||
#include "cmLocalVisualStudio10Generator.h"
|
#include "cmLocalVisualStudio10Generator.h"
|
||||||
#include "cmMakefile.h"
|
#include "cmMakefile.h"
|
||||||
#include "cmSourceFile.h"
|
#include "cmSourceFile.h"
|
||||||
@@ -3007,21 +3008,8 @@ bool cmVisualStudio10TargetGenerator::ComputeCudaLinkOptions(
|
|||||||
Options& cudaLinkOptions = *pOptions;
|
Options& cudaLinkOptions = *pOptions;
|
||||||
|
|
||||||
// Determine if we need to do a device link
|
// Determine if we need to do a device link
|
||||||
bool doDeviceLinking = false;
|
bool doDeviceLinking = requireDeviceLinking(
|
||||||
if (const char* resolveDeviceSymbols =
|
*this->GeneratorTarget, *this->LocalGenerator, configName);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cudaLinkOptions.AddFlag("PerformDeviceLink",
|
cudaLinkOptions.AddFlag("PerformDeviceLink",
|
||||||
doDeviceLinking ? "true" : "false");
|
doDeviceLinking ? "true" : "false");
|
||||||
|
@@ -359,6 +359,7 @@ CMAKE_CXX_SOURCES="\
|
|||||||
cmLinkDirectoriesCommand \
|
cmLinkDirectoriesCommand \
|
||||||
cmLinkItem \
|
cmLinkItem \
|
||||||
cmLinkLineComputer \
|
cmLinkLineComputer \
|
||||||
|
cmLinkLineDeviceComputer \
|
||||||
cmListCommand \
|
cmListCommand \
|
||||||
cmListFileCache \
|
cmListFileCache \
|
||||||
cmLocalCommonGenerator \
|
cmLocalCommonGenerator \
|
||||||
|
Reference in New Issue
Block a user