Skip to content

Commit 5f62f14

Browse files
committed
Added support for multi-GPU
1 parent 9592d98 commit 5f62f14

3 files changed

Lines changed: 28 additions & 9 deletions

File tree

src/algorithm/APRConverter.hpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -421,7 +421,7 @@ inline void APRConverter<ImageType>::processOnGpu(int numOfStream, int numOfStre
421421
pinnedBuffer.copyFromMesh(*input_images[numOfStream]);
422422

423423
for (int i = numOfStream; i < numOfImages; i += numOfStreams) {
424-
std::cout << "Processing image " << i << " on stream " << numOfStream << std::endl;
424+
std::cout << "Processing image " << i << " on GPU " << gpt.getCudaDeviceID() << " on stream " << numOfStream << std::endl;
425425

426426
// ---- Send image to GPU
427427
gpt.sendDataToGpu();
@@ -480,13 +480,18 @@ inline bool APRConverter<ImageType>::get_apr_cuda_multistreams(std::vector<APR*>
480480

481481
APRTimer t(true);
482482

483+
// Get number of available GPUs, created GPU streams will be distributed evenly on those GPUs
484+
const int numberOfGpus = getNumberOfGpu();
485+
std::cout << "Number of detected GPUs: " << numberOfGpus << std::endl;
486+
483487
// Create GpuProcessingTask for each stream and link it with pinnedBuffer
484488
std::vector<GpuProcessingTask<ImageType>> gpts;
485489
t.start_timer("Creating GPTs");
486490
std::vector<std::future<void>> gpts_futures; gpts_futures.resize(numOfStreams);
487491
for (int i = 0; i < numOfStreams; ++i) {
488-
//par.noise_sd_estimate = i;
489-
gpts.emplace_back(GpuProcessingTask<ImageType>(pinnedBuffers[i], par, aAPRs[0]->level_max()));
492+
// Create GpuProcessingTask on provided GPU (via provided Cuda ID) and bind it with pinned memory buffer used
493+
// later for transfering images to GPU
494+
gpts.emplace_back(GpuProcessingTask<ImageType>(pinnedBuffers[i], par, aAPRs[0]->level_max(), i % numberOfGpus));
490495
}
491496
t.stop_timer();
492497

@@ -499,6 +504,7 @@ inline bool APRConverter<ImageType>::get_apr_cuda_multistreams(std::vector<APR*>
499504
std::ref(input_images), std::ref(gpts[i]), std::ref(pinnedBuffers[i]),
500505
std::ref(aAPRs), std::ref(intensities));
501506
}
507+
502508
// ...and wait for all jobs to finish
503509
for (int i = 0; i < numOfStreams; ++i) gpts_futures[i].get();
504510

src/algorithm/ComputeGradientCuda.cu

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,11 @@ void runSampleParts(ImgType** downsampled, GenInfo &aprInfo, ImgType *parts_cuda
370370
}
371371
};
372372

373+
int getNumberOfGpu() {
374+
int deviceCount = 0;
375+
checkCuda(cudaGetDeviceCount(&deviceCount));
376+
return deviceCount;
377+
}
373378

374379
class CudaStream {
375380
cudaStream_t iStream;
@@ -469,8 +474,8 @@ class GpuProcessingTask<U>::GpuProcessingTaskImpl {
469474

470475
public:
471476

472-
GpuProcessingTaskImpl(const PixelData<ImgType> &inputImage, const APRParameters &parameters, int maxLevel) :
473-
cudaDevID(0), // used for now only in testing new ideas, ideally we should discover CPU/GPU architecture and assing corrct GPU to correct CPU which involves also correct memory allocation and thread affinity....
477+
GpuProcessingTaskImpl(const PixelData<ImgType> &inputImage, const APRParameters &parameters, int maxLevel, int gpuCudaId) :
478+
cudaDevID(gpuCudaId), // used for now only in testing new ideas, ideally we should discover CPU/GPU architecture and assing corrct GPU to correct CPU which involves also correct memory allocation and thread affinity....
474479
cudaerr(cudaSetDevice(cudaDevID)),
475480
iCpuImage(inputImage),
476481
iStream(cudaStream.get()),
@@ -574,6 +579,8 @@ public:
574579
return std::move(lacs);
575580
}
576581

582+
int getCudaDeviceID() const { return cudaDevID; }
583+
577584
void sendDataToGpu() {
578585
cudaSetDevice(cudaDevID);
579586
// Set it and copy first before copying the image
@@ -652,8 +659,8 @@ public:
652659
};
653660

654661
template <typename ImgType>
655-
GpuProcessingTask<ImgType>::GpuProcessingTask(const PixelData<ImgType> &image, const APRParameters &parameters, int maxLevel)
656-
: impl{new GpuProcessingTaskImpl<ImgType>(image, parameters, maxLevel)} { }
662+
GpuProcessingTask<ImgType>::GpuProcessingTask(const PixelData<ImgType> &image, const APRParameters &parameters, int maxLevel, int gpuCudaID)
663+
: impl{new GpuProcessingTaskImpl<ImgType>(image, parameters, maxLevel, gpuCudaID)} { }
657664

658665
template <typename ImgType>
659666
GpuProcessingTask<ImgType>::~GpuProcessingTask() { }
@@ -670,6 +677,9 @@ void GpuProcessingTask<ImgType>::processOnGpu() {impl->processOnGpu();}
670677
template <typename ImgType>
671678
void GpuProcessingTask<ImgType>::sendDataToGpu() {impl->sendDataToGpu();}
672679

680+
template <typename ImgType>
681+
int GpuProcessingTask<ImgType>::getCudaDeviceID() const { return impl->getCudaDeviceID(); }
682+
673683
// explicit instantiation of handled types
674684
template class GpuProcessingTask<uint8_t>;
675685
template class GpuProcessingTask<int>;

src/algorithm/ComputeGradientCuda.hpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ void getGradient(PixelData<ImgType> &image, PixelData<ImgType> &grad_temp, Pixel
3535
void cudaDownsampledGradient(PixelData<float> &input, PixelData<float> &grad, const float hx, const float hy, const float hz);
3636
template<typename T> std::pair<T,T> cudaRunMinMax(PixelData<T> &input_image);
3737

38+
int getNumberOfGpu();
39+
3840
template <typename ImgType>
3941
class GpuProcessingTask {
4042
// Using PIMPL to seperate GPU code from CPU (this file is to be included in regular code not compiled with nvcc)
@@ -43,15 +45,16 @@ class GpuProcessingTask {
4345

4446
public:
4547

46-
GpuProcessingTask(const PixelData<ImgType> &image, const APRParameters &parameters, int maxLevel);
48+
GpuProcessingTask(const PixelData<ImgType> &image, const APRParameters &parameters, int maxLevel, int gpuCudaID = 0);
4749
~GpuProcessingTask();
4850
GpuProcessingTask(GpuProcessingTask&&);
4951

5052
LinearAccessCudaStructs<ImgType> getDataFromGpu();
5153
void processOnGpu();
5254
void sendDataToGpu();
5355

54-
void setBsplineOffset(float bspline_offset);
56+
int getCudaDeviceID() const;
57+
5558
};
5659

5760
#endif //LIBAPR_COMPUTEGRADIENTCUDA_HPP

0 commit comments

Comments
 (0)