4.1.5.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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#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 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;
}

///copie la string str en effaçant le caractère ch
/**	@param str : chaîne à copier
	@param ch : caractère à effacer
	@return string sans le caractère ch
*/
std::string asterics_eraseCharInStr(const std::string& str, char ch){
	std::string buffer = "";
	for(std::string::const_iterator it = str.begin(); it != str.end(); it++){
		if(*it != ch) buffer += *it;
	}
	return buffer;
}

///copie la string str en effaçant les caractères rmchs
/**	@param str : chaîne à copier
	@param rmchs : caractères à effacer
	@return string sans les caractères rmchs
*/
std::string asterics_eraseCharsInStr(const std::string& str, const std::string & rmchs){
	std::string buffer = str;
	for(std::string::const_iterator it = rmchs.begin(); it != rmchs.end(); it++){
		buffer = asterics_eraseCharInStr(buffer, *it);
	}
	return buffer;
}

///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){
	std::string onlyUuid(asterics_eraseCharsInStr(uuidSelectedDevice, "GPUMIG-"));
	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, onlyUuid)){
			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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
/***************************************
	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 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;
}

///copie la string str en effaçant le caractère ch
/**	@param str : chaîne à copier
	@param ch : caractère à effacer
	@return string sans le caractère ch
*/
std::string asterics_eraseCharInStr(const std::string& str, char ch){
	std::string buffer = "";
	for(std::string::const_iterator it = str.begin(); it != str.end(); it++){
		if(*it != ch) buffer += *it;
	}
	return buffer;
}

///copie la string str en effaçant les caractères rmchs
/**	@param str : chaîne à copier
	@param rmchs : caractères à effacer
	@return string sans les caractères rmchs
*/
std::string asterics_eraseCharsInStr(const std::string& str, const std::string & rmchs){
	std::string buffer = str;
	for(std::string::const_iterator it = rmchs.begin(); it != rmchs.end(); it++){
		buffer = asterics_eraseCharInStr(buffer, *it);
	}
	return buffer;
}

///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){
	std::string onlyUuid(asterics_eraseCharsInStr(uuidSelectedDevice, "GPUMIG-"));
	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, onlyUuid)){
			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.