3.3.1.2.2 : Le fichier asterics_cuda.cpp
Développons le fichier asterics_cuda.cpp :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#include <stdlib.h>
#include <cuda.h>
#include <cuda_runtime.h>

#include <sstream>
#include <iomanip>
#include <iostream>

#include "asterics_cuda.h"

///Get the number of cuda device
/**	@return number of Cuda device
*/
int asterics_getNbCudaDevice(){
	int deviceCount = 0;
	cudaError_t error_id = cudaGetDeviceCount(&deviceCount);
	if(error_id != cudaSuccess){
		printf("asterics_getNbCudaDevice : cudaGetDeviceCount returned %d\n-> %s\n", (int)error_id, cudaGetErrorString(error_id));
		printf("asterics_getNbCudaDevice : deviceCount = %d\n", deviceCount);
		printf("asterics_getNbCudaDevice : Result = FAIL\n");
		exit(EXIT_FAILURE);
	}
	// This function call returns 0 if there are no CUDA capable devices.
	if(deviceCount == 0){
		printf("asterics_getNbCudaDevice : There are no available device(s) that support CUDA\n");
	}else{
		printf("asterics_getNbCudaDevice : Detected %d CUDA Capable device(s)\n", deviceCount);
	}
	return deviceCount;
}

///Get some usefull GPU info
/**	@param[out] maxNbThreadPerBlockX : maximum number of thread per block on X
 * 	@param[out] maxNbBlockX : maximum number of block in the grid on X
 * 	@param[out] warpSize : number of thread per warp
 * 	@param deviceIndex : index of the device to be used
*/
void asterics_getGpuInfo(int & maxNbThreadPerBlockX, int & maxNbBlockX, int & warpSize, int deviceIndex){
	cudaSetDevice(deviceIndex);
	cudaDeviceProp deviceProp;
	cudaGetDeviceProperties(&deviceProp, deviceIndex);
	maxNbThreadPerBlockX = deviceProp.maxThreadsDim[0];
	maxNbBlockX = deviceProp.maxGridSize[0];
	warpSize = deviceProp.warpSize;
}

///Get some usefull GPU info
/**	@param[out] maxNbThreadPerBlockX : maximum number of thread per block on X
 * 	@param[out] maxNbBlockX : maximum number of block in the grid on X
 * 	@param[out] memSize : number of bytes in the GPU memory
 * 	@param deviceIndex : index of the device to be used
*/
void asterics_getGpuInfoMem(size_t & maxNbThreadPerBlockX, size_t & maxNbBlockX, size_t & memSize, int deviceIndex){
	cudaSetDevice(deviceIndex);
	cudaDeviceProp deviceProp;
	cudaGetDeviceProperties(&deviceProp, deviceIndex);
	maxNbThreadPerBlockX = deviceProp.maxThreadsDim[0];
	maxNbBlockX = deviceProp.maxGridSize[0];
	memSize = deviceProp.totalGlobalMem;
}

///Get the UUID of the given Cuda Device
/**	@param deviceProp : Cuda Device to be used
 * 	@return corresponding UUID
*/
std::string asterics_getUuid(const cudaDeviceProp & deviceProp){
	const unsigned char * tabByte = (const unsigned char *)deviceProp.uuid.bytes;
	std::stringstream out;
	for(int i(0); i < 16; ++i){
// 		printf("%02x,", (unsigned int)(tabByte[i]));
		out << std::hex << std::setfill('0') << std::setw(2) << (unsigned int)tabByte[i];
	}
	return "GPU-" + out.str();
}

///Check if two string start the same way
/**	@param str : string to be tested
	@param beginig : begining to be checked
	@return true if str starts as beginig
*/
bool asterics_isSameBegining(const std::string & str, const std::string & beginig){
	if(str.size() < beginig.size()) return false;
	std::string::const_iterator it = str.begin();
	std::string::const_iterator it2 = beginig.begin();
	while(it != str.end() && it2 != beginig.end()){
		if(*it != *it2){ return false;}
		it++;
		it2++;
	}
	return true;
}

///Set the cuda device
/**	@param uuidSelectedDevice : uuid of the device to be used (or the begining)
 * 	@return id of the choosen device
*/
int asterics_setDevice(const std::string & uuidSelectedDevice){
	int deviceCount = asterics_getNbCudaDevice();
	for(int dev = 0; dev < deviceCount; ++dev){
		cudaSetDevice(dev);
		cudaDeviceProp deviceProp;
		cudaGetDeviceProperties(&deviceProp, dev);
		std::string uuid(asterics_getUuid(deviceProp));
		if(asterics_isSameBegining(uuid, uuidSelectedDevice)){
			std::cout << "asterics_setDevice : set device " << dev << " with UUID = " << uuid << std::endl;
			cudaSetDevice(dev);
			return dev;
		}
	}
	return 0;
}


Le fichier asterics_cuda.cpp complet.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
/***************************************
	Auteur : Pierre Aubert
	Mail : pierre.aubert@lapp.in2p3.fr
	Licence : CeCILL-C
****************************************/

#include <stdlib.h>
#include <cuda.h>
#include <cuda_runtime.h>

#include <sstream>
#include <iomanip>
#include <iostream>

#include "asterics_cuda.h"

///Get the number of cuda device
/**	@return number of Cuda device
*/
int asterics_getNbCudaDevice(){
	int deviceCount = 0;
	cudaError_t error_id = cudaGetDeviceCount(&deviceCount);
	if(error_id != cudaSuccess){
		printf("asterics_getNbCudaDevice : cudaGetDeviceCount returned %d\n-> %s\n", (int)error_id, cudaGetErrorString(error_id));
		printf("asterics_getNbCudaDevice : deviceCount = %d\n", deviceCount);
		printf("asterics_getNbCudaDevice : Result = FAIL\n");
		exit(EXIT_FAILURE);
	}
	// This function call returns 0 if there are no CUDA capable devices.
	if(deviceCount == 0){
		printf("asterics_getNbCudaDevice : There are no available device(s) that support CUDA\n");
	}else{
		printf("asterics_getNbCudaDevice : Detected %d CUDA Capable device(s)\n", deviceCount);
	}
	return deviceCount;
}

///Get some usefull GPU info
/**	@param[out] maxNbThreadPerBlockX : maximum number of thread per block on X
 * 	@param[out] maxNbBlockX : maximum number of block in the grid on X
 * 	@param[out] warpSize : number of thread per warp
 * 	@param deviceIndex : index of the device to be used
*/
void asterics_getGpuInfo(int & maxNbThreadPerBlockX, int & maxNbBlockX, int & warpSize, int deviceIndex){
	cudaSetDevice(deviceIndex);
	cudaDeviceProp deviceProp;
	cudaGetDeviceProperties(&deviceProp, deviceIndex);
	maxNbThreadPerBlockX = deviceProp.maxThreadsDim[0];
	maxNbBlockX = deviceProp.maxGridSize[0];
	warpSize = deviceProp.warpSize;
}

///Get some usefull GPU info
/**	@param[out] maxNbThreadPerBlockX : maximum number of thread per block on X
 * 	@param[out] maxNbBlockX : maximum number of block in the grid on X
 * 	@param[out] memSize : number of bytes in the GPU memory
 * 	@param deviceIndex : index of the device to be used
*/
void asterics_getGpuInfoMem(size_t & maxNbThreadPerBlockX, size_t & maxNbBlockX, size_t & memSize, int deviceIndex){
	cudaSetDevice(deviceIndex);
	cudaDeviceProp deviceProp;
	cudaGetDeviceProperties(&deviceProp, deviceIndex);
	maxNbThreadPerBlockX = deviceProp.maxThreadsDim[0];
	maxNbBlockX = deviceProp.maxGridSize[0];
	memSize = deviceProp.totalGlobalMem;
}

///Get the UUID of the given Cuda Device
/**	@param deviceProp : Cuda Device to be used
 * 	@return corresponding UUID
*/
std::string asterics_getUuid(const cudaDeviceProp & deviceProp){
	const unsigned char * tabByte = (const unsigned char *)deviceProp.uuid.bytes;
	std::stringstream out;
	for(int i(0); i < 16; ++i){
// 		printf("%02x,", (unsigned int)(tabByte[i]));
		out << std::hex << std::setfill('0') << std::setw(2) << (unsigned int)tabByte[i];
	}
	return "GPU-" + out.str();
}

///Check if two string start the same way
/**	@param str : string to be tested
	@param beginig : begining to be checked
	@return true if str starts as beginig
*/
bool asterics_isSameBegining(const std::string & str, const std::string & beginig){
	if(str.size() < beginig.size()) return false;
	std::string::const_iterator it = str.begin();
	std::string::const_iterator it2 = beginig.begin();
	while(it != str.end() && it2 != beginig.end()){
		if(*it != *it2){ return false;}
		it++;
		it2++;
	}
	return true;
}

///Set the cuda device
/**	@param uuidSelectedDevice : uuid of the device to be used (or the begining)
 * 	@return id of the choosen device
*/
int asterics_setDevice(const std::string & uuidSelectedDevice){
	int deviceCount = asterics_getNbCudaDevice();
	for(int dev = 0; dev < deviceCount; ++dev){
		cudaSetDevice(dev);
		cudaDeviceProp deviceProp;
		cudaGetDeviceProperties(&deviceProp, dev);
		std::string uuid(asterics_getUuid(deviceProp));
		if(asterics_isSameBegining(uuid, uuidSelectedDevice)){
			std::cout << "asterics_setDevice : set device " << dev << " with UUID = " << uuid << std::endl;
			cudaSetDevice(dev);
			return dev;
		}
	}
	return 0;
}


Vous pouvez télécharger le fichier ici.