2014-11-26 17:19:46 +00:00
|
|
|
//============================================================================
|
|
|
|
// Copyright (c) Kitware, Inc.
|
|
|
|
// All rights reserved.
|
|
|
|
// See LICENSE.txt for details.
|
2019-04-15 23:24:21 +00:00
|
|
|
//
|
2014-11-26 17:19:46 +00:00
|
|
|
// This software is distributed WITHOUT ANY WARRANTY; without even
|
|
|
|
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
|
|
// PURPOSE. See the above copyright notice for more information.
|
|
|
|
//============================================================================
|
|
|
|
#ifndef vtk_m_cont_cuda_ChooseCudaDevice_h
|
|
|
|
#define vtk_m_cont_cuda_ChooseCudaDevice_h
|
|
|
|
|
|
|
|
#include <vtkm/cont/ErrorExecution.h>
|
|
|
|
|
2021-08-26 19:27:03 +00:00
|
|
|
#include <vtkm/cont/RuntimeDeviceInformation.h>
|
2017-01-09 21:15:32 +00:00
|
|
|
#include <vtkm/cont/cuda/ErrorCuda.h>
|
2021-11-19 19:32:18 +00:00
|
|
|
#include <vtkm/cont/cuda/internal/DeviceAdapterTagCuda.h>
|
2021-08-26 19:27:03 +00:00
|
|
|
#include <vtkm/cont/cuda/internal/RuntimeDeviceConfigurationCuda.h>
|
2016-12-07 22:13:02 +00:00
|
|
|
|
2014-11-26 17:19:46 +00:00
|
|
|
#include <algorithm>
|
2021-08-26 19:27:03 +00:00
|
|
|
#include <set>
|
2014-11-26 17:19:46 +00:00
|
|
|
#include <vector>
|
|
|
|
|
2017-09-21 14:33:17 +00:00
|
|
|
VTKM_THIRDPARTY_PRE_INCLUDE
|
|
|
|
#include <cuda.h>
|
|
|
|
VTKM_THIRDPARTY_POST_INCLUDE
|
|
|
|
|
2017-05-18 14:29:41 +00:00
|
|
|
namespace vtkm
|
|
|
|
{
|
|
|
|
namespace cont
|
|
|
|
{
|
|
|
|
namespace cuda
|
|
|
|
{
|
2014-11-26 17:19:46 +00:00
|
|
|
|
2017-05-18 14:29:41 +00:00
|
|
|
namespace
|
|
|
|
{
|
2014-11-26 17:19:46 +00:00
|
|
|
struct compute_info
|
|
|
|
{
|
2015-05-07 22:34:06 +00:00
|
|
|
compute_info(cudaDeviceProp prop, int index)
|
|
|
|
{
|
|
|
|
this->Index = index;
|
|
|
|
this->Major = prop.major;
|
2014-11-26 17:19:46 +00:00
|
|
|
|
2015-05-07 22:34:06 +00:00
|
|
|
this->MemorySize = prop.totalGlobalMem;
|
2017-05-18 14:29:41 +00:00
|
|
|
this->Performance =
|
|
|
|
prop.multiProcessorCount * prop.maxThreadsPerMultiProcessor * (prop.clockRate / 100000.0);
|
2014-11-26 17:19:46 +00:00
|
|
|
|
2015-05-07 22:34:06 +00:00
|
|
|
//9999 is equal to emulation make sure it is a super bad device
|
2017-05-18 14:29:41 +00:00
|
|
|
if (this->Major >= 9999)
|
2015-05-07 22:34:06 +00:00
|
|
|
{
|
|
|
|
this->Major = -1;
|
|
|
|
this->Performance = -1;
|
|
|
|
}
|
2014-11-26 17:19:46 +00:00
|
|
|
}
|
|
|
|
|
2015-05-07 22:34:06 +00:00
|
|
|
//sort from fastest to slowest
|
|
|
|
bool operator<(const compute_info other) const
|
2014-11-26 17:19:46 +00:00
|
|
|
{
|
2015-06-30 12:18:16 +00:00
|
|
|
//if we are both SM3 or greater check performance
|
2015-05-07 22:34:06 +00:00
|
|
|
//if we both the same SM level check performance
|
2017-05-18 14:29:41 +00:00
|
|
|
if ((this->Major >= 3 && other.Major >= 3) || (this->Major == other.Major))
|
2015-05-07 22:34:06 +00:00
|
|
|
{
|
2018-03-20 18:53:39 +00:00
|
|
|
return betterPerformance(other);
|
2015-05-07 22:34:06 +00:00
|
|
|
}
|
|
|
|
//prefer the greater SM otherwise
|
|
|
|
return this->Major > other.Major;
|
2014-11-26 17:19:46 +00:00
|
|
|
}
|
|
|
|
|
2018-03-20 18:53:39 +00:00
|
|
|
bool betterPerformance(const compute_info other) const
|
2014-11-26 17:19:46 +00:00
|
|
|
{
|
2017-05-18 14:29:41 +00:00
|
|
|
if (this->Performance == other.Performance)
|
2015-05-07 22:34:06 +00:00
|
|
|
{
|
2017-05-18 14:29:41 +00:00
|
|
|
if (this->MemorySize == other.MemorySize)
|
2014-11-26 17:19:46 +00:00
|
|
|
{
|
2015-05-07 22:34:06 +00:00
|
|
|
//prefer first device over second device
|
|
|
|
//this will be subjective I bet
|
|
|
|
return this->Index < other.Index;
|
2014-11-26 17:19:46 +00:00
|
|
|
}
|
2015-05-07 22:34:06 +00:00
|
|
|
return this->MemorySize > other.MemorySize;
|
|
|
|
}
|
|
|
|
return this->Performance > other.Performance;
|
2014-11-26 17:19:46 +00:00
|
|
|
}
|
|
|
|
|
2015-05-07 22:34:06 +00:00
|
|
|
int GetIndex() const { return Index; }
|
2014-11-26 17:19:46 +00:00
|
|
|
|
|
|
|
private:
|
2015-05-07 22:34:06 +00:00
|
|
|
int Index;
|
|
|
|
int Major;
|
|
|
|
size_t MemorySize;
|
2015-06-30 12:16:42 +00:00
|
|
|
double Performance;
|
2014-11-26 17:19:46 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
///Returns the fastest cuda device id that the current system has
|
|
|
|
///A result of zero means no cuda device has been found
|
|
|
|
static int FindFastestDeviceId()
|
|
|
|
{
|
2021-08-26 19:27:03 +00:00
|
|
|
auto cudaDeviceConfig = dynamic_cast<
|
|
|
|
vtkm::cont::internal::RuntimeDeviceConfiguration<vtkm::cont::DeviceAdapterTagCuda>&>(
|
|
|
|
vtkm::cont::RuntimeDeviceInformation{}.GetRuntimeConfiguration(
|
|
|
|
vtkm::cont::DeviceAdapterTagCuda()));
|
|
|
|
vtkm::Id numDevices;
|
|
|
|
cudaDeviceConfig.GetMaxDevices(numDevices);
|
|
|
|
|
|
|
|
// multiset stores elements in sorted order (allows duplicate values)
|
|
|
|
std::multiset<compute_info> devices;
|
|
|
|
std::vector<cudaDeviceProp> cudaProp;
|
|
|
|
cudaDeviceConfig.GetCudaDeviceProp(cudaProp);
|
|
|
|
for (int i = 0; i < numDevices; ++i)
|
2016-12-07 22:13:02 +00:00
|
|
|
{
|
2021-08-26 19:27:03 +00:00
|
|
|
if (cudaProp[i].computeMode != cudaComputeModeProhibited)
|
2016-12-07 22:13:02 +00:00
|
|
|
{
|
2021-08-26 19:27:03 +00:00
|
|
|
devices.emplace(cudaProp[i], i);
|
2014-11-26 17:19:46 +00:00
|
|
|
}
|
2016-12-07 22:13:02 +00:00
|
|
|
}
|
2014-11-26 17:19:46 +00:00
|
|
|
|
2021-08-26 19:27:03 +00:00
|
|
|
return devices.size() > 0 ? devices.begin()->GetIndex() : 0;
|
|
|
|
}
|
2014-11-26 17:19:46 +00:00
|
|
|
|
2021-08-26 19:27:03 +00:00
|
|
|
/// Sets the current cuda device to the value returned by FindFastestDeviceId
|
|
|
|
static void SetFastestDeviceId()
|
|
|
|
{
|
|
|
|
auto deviceId = FindFastestDeviceId();
|
|
|
|
vtkm::cont::RuntimeDeviceInformation{}
|
|
|
|
.GetRuntimeConfiguration(vtkm::cont::DeviceAdapterTagCuda())
|
|
|
|
.SetDeviceInstance(deviceId);
|
2014-11-26 17:19:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} //namespace
|
|
|
|
|
|
|
|
#endif
|