Skip to content

Commit

Permalink
[popsift] test whether image fits into CUDA textures
Browse files Browse the repository at this point in the history
  • Loading branch information
Carsten Griwodz committed Apr 29, 2020
1 parent 149de05 commit 18a9032
Show file tree
Hide file tree
Showing 5 changed files with 469 additions and 17 deletions.
8 changes: 8 additions & 0 deletions src/popsift/common/debug_macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,14 @@ class BriefDuration
std::cerr << __FILE__ << ":" << __LINE__ << std::endl << " " << s << std::endl; \
}

#define POP_WARN(s) { \
std::cerr << __FILE__ << ":" << __LINE__ << std::endl; \
std::cerr << " WARNING: " << s << std::endl; \
}
#define POP_CUDA_WARN(err,s) { \
std::cerr << __FILE__ << ":" << __LINE__ << std::endl; \
std::cerr << " WARNING: " << s << cudaGetErrorString(err) << std::endl; \
}
#define POP_CUDA_FATAL(err,s) { \
std::cerr << __FILE__ << ":" << __LINE__ << std::endl; \
std::cerr << " " << s << cudaGetErrorString(err) << std::endl; \
Expand Down
230 changes: 226 additions & 4 deletions src/popsift/common/device_prop.cu
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,24 @@ using namespace std;

device_prop_t::device_prop_t( )
{
int currentDevice;
cudaError_t err;

err = cudaGetDevice( &currentDevice );
POP_CUDA_FATAL_TEST( err, "Cannot get the current CUDA device" );

err = cudaGetDeviceCount( &_num_devices );
POP_CUDA_FATAL_TEST( err, "Cannot count devices" );

_properties.resize(_num_devices);

for( int n=0; n<_num_devices; n++ ) {
cudaDeviceProp* p;
_properties.push_back( p = new cudaDeviceProp );
err = cudaGetDeviceProperties( p, n );
_properties[n] = new cudaDeviceProp;
err = cudaGetDeviceProperties( _properties[n], n );
POP_CUDA_FATAL_TEST( err, "Cannot get properties for a device" );
}
err = cudaSetDevice( 0 );

err = cudaSetDevice( currentDevice );
POP_CUDA_FATAL_TEST( err, "Cannot set device 0" );
}

Expand Down Expand Up @@ -86,5 +92,221 @@ device_prop_t::~device_prop_t( )
}
}

bool device_prop_t::checkLimit_2DtexLinear( int& width, int& height, bool printWarn ) const
{
bool returnSuccess = true;
int currentDevice;
cudaError_t err;

err = cudaGetDevice( &currentDevice );
if( err != cudaSuccess )
{
POP_CUDA_WARN( err, "Cannot get current CUDA device" );
return true;
}

if( currentDevice >= _properties.size() )
{
POP_WARN( "CUDA device was not registered at program start" );
return true;
}

const cudaDeviceProp* ptr = _properties[currentDevice];
if( width > ptr->maxTexture2DLayered[0] )
{
if( printWarn )
{
std::cerr << __FILE__ << ":" << __LINE__
<< ": CUDA device " << currentDevice << std::endl
<< " does not support 2D linear textures " << width
<< " pixels wide." << endl;
}
width = ptr->maxTexture2DLayered[0];
returnSuccess = false;
}
if( height > ptr->maxTexture2DLayered[1] )
{
if( returnSuccess && printWarn )
{
std::cerr << __FILE__ << ":" << __LINE__
<< ": CUDA device " << currentDevice << std::endl
<< " does not support 2D linear textures " << height
<< " pixels high." << endl;
}
height = ptr->maxTexture2DLayered[1];
returnSuccess = false;
}

return returnSuccess;
}

bool device_prop_t::checkLimit_2DtexArray( int& width, int& height, bool printWarn ) const
{
bool returnSuccess = true;
int currentDevice;
cudaError_t err;

err = cudaGetDevice( &currentDevice );
if( err != cudaSuccess )
{
POP_CUDA_WARN( err, "Cannot get current CUDA device" );
return true;
}

if( currentDevice >= _properties.size() )
{
POP_WARN( "CUDA device was not registered at program start" );
return true;
}

const cudaDeviceProp* ptr = _properties[currentDevice];
if( width > ptr->maxTexture2D[0] )
{
if( printWarn )
{
std::cerr << __FILE__ << ":" << __LINE__
<< ": CUDA device " << currentDevice << std::endl
<< " does not support 2D array textures " << width
<< " pixels wide." << endl;
}
width = ptr->maxTexture2D[0];
returnSuccess = false;
}
if( height > ptr->maxTexture2D[1] )
{
if( returnSuccess && printWarn )
{
std::cerr << __FILE__ << ":" << __LINE__
<< ": CUDA device " << currentDevice << std::endl
<< " does not support 2D array textures " << height
<< " pixels high." << endl;
}
height = ptr->maxTexture2D[1];
returnSuccess = false;
}

return returnSuccess;
}

bool device_prop_t::checkLimit_2DtexLayered( int& width, int& height, int& layers, bool printWarn ) const
{
bool returnSuccess = true;
int currentDevice;
cudaError_t err;

err = cudaGetDevice( &currentDevice );
if( err != cudaSuccess )
{
POP_CUDA_WARN( err, "Cannot get current CUDA device" );
return true;
}

if( currentDevice >= _properties.size() )
{
POP_WARN( "CUDA device was not registered at program start" );
return true;
}

const cudaDeviceProp* ptr = _properties[currentDevice];
if( width > ptr->maxTexture2DLayered[0] )
{
if( printWarn )
{
std::cerr << __FILE__ << ":" << __LINE__
<< ": CUDA device " << currentDevice << std::endl
<< " does not support 2D array textures " << width
<< " pixels wide." << endl;
}
width = ptr->maxTexture2DLayered[0];
returnSuccess = false;
}
if( height > ptr->maxTexture2DLayered[1] )
{
if( returnSuccess && printWarn )
{
std::cerr << __FILE__ << ":" << __LINE__
<< ": CUDA device " << currentDevice << std::endl
<< " does not support 2D array textures " << height
<< " pixels high." << endl;
}
height = ptr->maxTexture2DLayered[1];
returnSuccess = false;
}
if( layers > ptr->maxTexture2DLayered[2] )
{
if( returnSuccess && printWarn )
{
std::cerr << __FILE__ << ":" << __LINE__
<< ": CUDA device " << currentDevice << std::endl
<< " does not support 2D array textures " << layers
<< " pixels deep." << endl;
}
layers = ptr->maxTexture2DLayered[2];
returnSuccess = false;
}

return returnSuccess;
}

bool device_prop_t::checkLimit_2DsurfLayered( int& width, int& height, int& layers, bool printWarn ) const
{
bool returnSuccess = true;
int currentDevice;
cudaError_t err;

err = cudaGetDevice( &currentDevice );
if( err != cudaSuccess )
{
POP_CUDA_WARN( err, "Cannot get current CUDA device" );
return true;
}

if( currentDevice >= _properties.size() )
{
POP_WARN( "CUDA device was not registered at program start" );
return true;
}

const cudaDeviceProp* ptr = _properties[currentDevice];
if( width > ptr->maxSurface2DLayered[0] )
{
if( printWarn )
{
std::cerr << __FILE__ << ":" << __LINE__
<< ": CUDA device " << currentDevice << std::endl
<< " does not support layered 2D surfaces " << width
<< " bytes wide." << endl;
}
width = ptr->maxSurface2DLayered[0];
returnSuccess = false;
}
if( height > ptr->maxSurface2DLayered[1] )
{
if( returnSuccess && printWarn )
{
std::cerr << __FILE__ << ":" << __LINE__
<< ": CUDA device " << currentDevice << std::endl
<< " does not support layered 2D surfaces " << height
<< " pixels high." << endl;
}
height = ptr->maxSurface2DLayered[1];
returnSuccess = false;
}
if( layers > ptr->maxSurface2DLayered[2] )
{
if( returnSuccess && printWarn )
{
std::cerr << __FILE__ << ":" << __LINE__
<< ": CUDA device " << currentDevice << std::endl
<< " does not support layered 2D surfaces " << layers
<< " pixels deep." << endl;
}
layers = ptr->maxSurface2DLayered[2];
returnSuccess = false;
}

return returnSuccess;
}

}}

66 changes: 66 additions & 0 deletions src/popsift/common/device_prop.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,78 @@ class device_prop_t
{
int _num_devices;
std::vector<cudaDeviceProp*> _properties;

public:
enum {
do_warn = true,
dont_warn = false
};

public:
device_prop_t( );
~device_prop_t( );

void print( );
void set( int n, bool print_choice = false );

/** Check if a request exceeds the current CUDA device's limit in
* texture2Dlinear dimensions. texture2Dlinear is based on CUDA memory that
* can be accessed directly (i.e. no CudaArray).
* @param[in,out] width Desired width of the texture.
* @param[in,out] height Desired height of the texture.
* @param[in] printWarn if true, print warnings to cerr if desired width
* or height exceeds limits.
* @return { true if the desired width and height are possible.
* false if one or both of the desired width and height are impossible.
* The desired width or height (or both) are replaced by the limit.}
*/
bool checkLimit_2DtexLinear( int& width, int& height, bool printWarn ) const;

/** Check if a request exceeds the current CUDA device's limit in
* texture2D dimensions. texture2D is based on CUDA Arrays, which have
* invisible layout and can only be filled with cudaMemcpy.
* @param[in,out] width Desired width of the texture.
* @param[in,out] height Desired height of the texture.
* @param[in] printWarn if true, print warnings to cerr if desired width
* or height exceeds limits.
* @return { true if the desired width and height are possible.
* false if one or both of the desired width and height are impossible.
* The desired width or height (or both) are replaced by the limit.}
*/
bool checkLimit_2DtexArray( int& width, int& height, bool printWarn ) const;

/** Check if a request exceeds the current CUDA device's limit in
* texture2DLayered dimensions. texture2DLayered refers to a 3D structure, where
* interpolation happens only in 3D, effectively creating layers.
* @param[in,out] width Desired width of the texture.
* @param[in,out] height Desired height of the texture.
* @param[in,out] layers Desired depth of the texture.
* @param[in] printWarn if true, print warnings to cerr if desired width
* or height exceeds limits.
* @return { true if the desired width, height and depth are possible.
* false if one or both of the desired width and height are impossible.
* The desired width, height and layers are replaced by the limit
* if they exceed it.}
*/
bool checkLimit_2DtexLayered( int& width, int& height, int& layers,
bool printWarn ) const;

/** Check if a request exceeds the current CUDA device's limit in
* surface2DLayered dimensions. surface2DLayered is the writable equivalent
* to texture2DLayered, but the width must be given in bytes, not elements.
* Since we use float, images cannot be as wide as expected.
* @param[in,out] width Desired width of the texture.
* @param[in,out] height Desired height of the texture.
* @param[in,out] layers Desired depth of the texture.
* @param[in] printWarn if true, print warnings to cerr if desired width
* or height exceeds limits.
* @return { true if the desired width, height and depth are possible.
* false if one or both of the desired width and height are impossible.
* The desired width, height and layers are replaced by the limit
* if they exceed it.}
*/
bool checkLimit_2DsurfLayered( int& width, int& height, int& layers,
bool printWarn ) const;
};

}}
Expand Down
Loading

0 comments on commit 18a9032

Please sign in to comment.