Spaces:
Runtime error
Runtime error
__global__ void dummy_kernel() {} | |
bool binary_exists_for_current_device() | |
{ | |
// check against the dummy_kernel | |
// if we're unable to get the attributes, then | |
// we didn't compile a binary compatible with the current device | |
cudaFuncAttributes attr; | |
cudaError_t error = cudaFuncGetAttributes(&attr, dummy_kernel); | |
// clear the CUDA global error state if we just set it, so that | |
// check_cuda_error doesn't complain | |
if (cudaSuccess != error) (void)cudaGetLastError(); | |
return cudaSuccess == error; | |
} | |
void list_devices(void) | |
{ | |
int deviceCount; | |
cudaGetDeviceCount(&deviceCount); | |
if(deviceCount == 0) | |
{ | |
std::cout << "There is no device supporting CUDA" << std::endl; | |
} | |
int selected_device; | |
cudaGetDevice(&selected_device); | |
for (int dev = 0; dev < deviceCount; ++dev) | |
{ | |
cudaDeviceProp deviceProp; | |
cudaGetDeviceProperties(&deviceProp, dev); | |
if(dev == 0) | |
{ | |
if(deviceProp.major == 9999 && deviceProp.minor == 9999) | |
std::cout << "There is no device supporting CUDA." << std::endl; | |
else if(deviceCount == 1) | |
std::cout << "There is 1 device supporting CUDA" << std:: endl; | |
else | |
std::cout << "There are " << deviceCount << " devices supporting CUDA" << std:: endl; | |
} | |
std::cout << "\nDevice " << dev << ": \"" << deviceProp.name << "\""; | |
if(dev == selected_device) | |
std::cout << " [SELECTED]"; | |
std::cout << std::endl; | |
std::cout << " Major revision number: " << deviceProp.major << std::endl; | |
std::cout << " Minor revision number: " << deviceProp.minor << std::endl; | |
std::cout << " Total amount of global memory: " << deviceProp.totalGlobalMem << " bytes" << std::endl; | |
} | |
std::cout << std::endl; | |
} | |
// provide next, which c++03 doesn't have | |
template<typename Iterator> Iterator my_next(Iterator iter) | |
{ | |
return ++iter; | |
} | |
std::vector<int> CUDATestDriver::target_devices(const ArgumentMap &kwargs) | |
{ | |
std::vector<int> result; | |
// by default, test all devices in the system (device id -1) | |
int device_id = kwargs.count("device") ? atoi(kwargs.find("device")->second.c_str()) : -1; | |
if(device_id < 0) | |
{ | |
// target all devices in the system | |
int count = 0; | |
cudaGetDeviceCount(&count); | |
result.resize(count); | |
std::iota(result.begin(), result.end(), 0); | |
} | |
else | |
{ | |
// target the specified device | |
result = std::vector<int>(1,device_id); | |
} | |
return result; | |
} | |
bool CUDATestDriver::check_cuda_error(bool concise) | |
{ | |
cudaError_t const error = cudaGetLastError(); | |
if(cudaSuccess != error) | |
{ | |
if(!concise) | |
{ | |
std::cout << "[ERROR] CUDA error detected before running tests: [" | |
<< std::string(cudaGetErrorName(error)) | |
<< ": " | |
<< std::string(cudaGetErrorString(error)) | |
<< "]" << std::endl; | |
} | |
} | |
return cudaSuccess != error; | |
} | |
bool CUDATestDriver::post_test_sanity_check(const UnitTest &test, bool concise) | |
{ | |
cudaError_t const error = cudaDeviceSynchronize(); | |
if(cudaSuccess != error) | |
{ | |
if(!concise) | |
{ | |
std::cout << "\t[ERROR] CUDA error detected after running " << test.name << ": [" | |
<< std::string(cudaGetErrorName(error)) | |
<< ": " | |
<< std::string(cudaGetErrorString(error)) | |
<< "]" << std::endl; | |
} | |
} | |
return cudaSuccess == error; | |
} | |
bool CUDATestDriver::run_tests(const ArgumentSet &args, const ArgumentMap &kwargs) | |
{ | |
bool verbose = kwargs.count("verbose"); | |
bool concise = kwargs.count("concise"); | |
if(verbose && concise) | |
{ | |
std::cout << "--verbose and --concise cannot be used together" << std::endl; | |
exit(EXIT_FAILURE); | |
return false; | |
} | |
// check error status before doing anything | |
if(check_cuda_error(concise)) return false; | |
bool result = true; | |
if(kwargs.count("verbose")) | |
{ | |
list_devices(); | |
} | |
// figure out which devices to target | |
std::vector<int> devices = target_devices(kwargs); | |
// target each device | |
for(std::vector<int>::iterator device = devices.begin(); | |
device != devices.end(); | |
++device) | |
{ | |
cudaDeviceSynchronize(); | |
// set the device | |
cudaSetDevice(*device); | |
// check if a binary exists for this device | |
// if none exists, skip the device silently unless this is the only one we're targeting | |
if(devices.size() > 1 && !binary_exists_for_current_device()) | |
{ | |
// note which device we're skipping | |
cudaDeviceProp deviceProp; | |
cudaGetDeviceProperties(&deviceProp, *device); | |
std::cout << "Skipping Device " << *device << ": \"" << deviceProp.name << "\"" << std::endl; | |
continue; | |
} | |
if(!concise) | |
{ | |
// note which device we're testing | |
cudaDeviceProp deviceProp; | |
cudaGetDeviceProperties(&deviceProp, *device); | |
std::cout << "Testing Device " << *device << ": \"" << deviceProp.name << "\"" << std::endl; | |
} | |
// check error status before running any tests | |
if(check_cuda_error(concise)) return false; | |
// run tests | |
result &= UnitTestDriver::run_tests(args, kwargs); | |
if(!concise && my_next(device) != devices.end()) | |
{ | |
// provide some separation between the output of separate tests | |
std::cout << std::endl; | |
} | |
} | |
return result; | |
} | |
int CUDATestDriver::current_device_architecture() const | |
{ | |
int current = -1; | |
cudaGetDevice(¤t); | |
cudaDeviceProp deviceProp; | |
cudaGetDeviceProperties(&deviceProp, current); | |
return 100 * deviceProp.major + 10 * deviceProp.minor; | |
} | |
UnitTestDriver &driver_instance(thrust::system::cuda::tag) | |
{ | |
static CUDATestDriver s_instance; | |
return s_instance; | |
} | |