|
#include <unittest/testframework.h> |
|
#include <unittest/cuda/testframework.h> |
|
#include <thrust/system/cuda/memory.h> |
|
#include <cuda_runtime.h> |
|
#include <numeric> |
|
|
|
__global__ void dummy_kernel() {} |
|
|
|
bool binary_exists_for_current_device() |
|
{ |
|
|
|
|
|
|
|
cudaFuncAttributes attr; |
|
cudaError_t error = cudaFuncGetAttributes(&attr, dummy_kernel); |
|
|
|
|
|
|
|
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; |
|
} |
|
|
|
|
|
template<typename Iterator> Iterator my_next(Iterator iter) |
|
{ |
|
return ++iter; |
|
} |
|
|
|
|
|
std::vector<int> CUDATestDriver::target_devices(const ArgumentMap &kwargs) |
|
{ |
|
std::vector<int> result; |
|
|
|
|
|
int device_id = kwargs.count("device") ? atoi(kwargs.find("device")->second.c_str()) : -1; |
|
|
|
if(device_id < 0) |
|
{ |
|
|
|
int count = 0; |
|
cudaGetDeviceCount(&count); |
|
|
|
result.resize(count); |
|
std::iota(result.begin(), result.end(), 0); |
|
} |
|
else |
|
{ |
|
|
|
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_smoke_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); |
|
} |
|
|
|
|
|
if(check_cuda_error(concise)) return false; |
|
|
|
bool result = true; |
|
|
|
if(kwargs.count("verbose")) |
|
{ |
|
list_devices(); |
|
} |
|
|
|
|
|
std::vector<int> devices = target_devices(kwargs); |
|
|
|
|
|
for(std::vector<int>::iterator device = devices.begin(); |
|
device != devices.end(); |
|
++device) |
|
{ |
|
cudaDeviceSynchronize(); |
|
|
|
|
|
cudaSetDevice(*device); |
|
|
|
|
|
|
|
if(devices.size() > 1 && !binary_exists_for_current_device()) |
|
{ |
|
|
|
cudaDeviceProp deviceProp; |
|
cudaGetDeviceProperties(&deviceProp, *device); |
|
|
|
std::cout << "Skipping Device " << *device << ": \"" << deviceProp.name << "\"" << std::endl; |
|
|
|
continue; |
|
} |
|
|
|
if(!concise) |
|
{ |
|
|
|
cudaDeviceProp deviceProp; |
|
cudaGetDeviceProperties(&deviceProp, *device); |
|
|
|
std::cout << "Testing Device " << *device << ": \"" << deviceProp.name << "\"" << std::endl; |
|
} |
|
|
|
|
|
if(check_cuda_error(concise)) return false; |
|
|
|
|
|
result &= UnitTestDriver::run_tests(args, kwargs); |
|
|
|
if(!concise && my_next(device) != devices.end()) |
|
{ |
|
|
|
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; |
|
} |
|
|
|
|