Skip to content

ENH: Implement GPU device selection functionality - #106

Open
axel-grc wants to merge 1 commit into
RTKConsortium:mainfrom
axel-grc:SetCudaDevice
Open

ENH: Implement GPU device selection functionality#106
axel-grc wants to merge 1 commit into
RTKConsortium:mainfrom
axel-grc:SetCudaDevice

Conversation

@axel-grc

@axel-grc axel-grc commented Sep 4, 2026

Copy link
Copy Markdown
Collaborator

No description provided.

@SimonRit SimonRit left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. I'm not too fond of the proposed implementation. If I understand it well, you're using the environment to store the value. I don't think ITKCudaCommon should change the env. Moreover, this is probably not thread safe. I would recommend something similar to m_GlobalDefaultNumberOfThreads in ITK:

@axel-grc

axel-grc commented Sep 7, 2026

Copy link
Copy Markdown
Collaborator Author

Since SWIG can't wrap free functions, the device selection is exposed as static CudaDataManager methods, surfaced in Python through the convenient itk.set_default_cuda_device helper.

@axel-grc

axel-grc commented Sep 7, 2026

Copy link
Copy Markdown
Collaborator Author

I think we need to handle the case where a gpu is selected for example on torch but another on cudacommon.
To be discussed.

@axel-grc
axel-grc requested a review from SimonRit September 7, 2026 15:19
Add the ability to select the GPU used by all freshly created
itk::CudaDataManager / itk::CudaImage objects instead of implicitly
picking the device with the maximum FLOPS.

A value of -1 (the default) keeps the previous automatic behavior
(max FLOPS device). The device is resolved with the following
precedence:

1. The value set explicitly via itk::SetDefaultCudaDevice;
2. Otherwise the ITK_CUDA_DEFAULT_DEVICE environment variable, if set;
3. Otherwise the device with the maximum FLOPS.

The value is stored in a mutex-protected static, mirroring
itk::MultiThreaderBase's pattern, and the environment variable is only
read, never written, by the module. Passing an out-of-range index throws
an itk::ExceptionObject.

Since ITK's wrapping cannot bind free functions, the selection is also
exposed through static CudaDataManager::SetDefaultDevice/GetDefaultDevice
methods, which the Python itk.set_default_cuda_device helper calls.

Add C++ and Python tests covering the precedence and error cases.

@SimonRit SimonRit left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, much better. Some minor changes requested. I'm not very fond of the delegates function, wouldn't wrapping the function work, like e.g. in PCT's MostLikelyPathFunction.i ?

}

/** Set the default device used by all subsequently created CudaDataManagers.
* Use -1 to reset to automatic selection (max FLOPS device). Delegates to itk::SetDefaultCudaDevice. */

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd say "Use -1 to automatically select the (first) device with the max FLOPS."

static void
SetDefaultDevice(int device);

/** Get the current default device (-1 means auto / max FLOPS). Delegates to itk::GetDefaultCudaDevice. */

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Idem "Get the current default device. -1 means automated selection of the (first) device with the max FLOPS."

Comment thread include/itkCudaUtil.h
CudaGetMaxFlopsDev();

/** Set the default device used by all subsequently created CudaDataManagers.
* Use -1 to reset to automatic (max FLOPS) selection. Overrides the

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Idem "Use -1 to automatically select the (first) device with the max FLOPS."

Comment thread include/itkCudaUtil.h
void CudaCommon_EXPORT
SetDefaultCudaDevice(int device);

/** Get the current default device (-1 means auto / max FLOPS).

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Idem "Get the current default device. -1 means automated selection of the (first) device with the max FLOPS."

Comment thread include/itkCudaUtil.h
SetDefaultCudaDevice(int device);

/** Get the current default device (-1 means auto / max FLOPS).
* Precedence: explicitly set value > ITK_CUDA_DEFAULT_DEVICE env var > auto. */

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A bit cryptic to me. "Explicitely set value takes precedence over the ITK_CUDA_DEFAULT_DEVICE which itself takes precedence over the automated value."

Comment on lines +30 to +31
m_Device = itk::CudaGetMaxFlopsDev();
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This block should be moved to GetDefaultCudaDevice in my opinion.

Comment thread src/itkCudaUtil.cxx
{
// The explicitly-set default device (-1 = auto). Only meaningful once
// IsInitialized is true. Env var is only a fallback until then.
bool IsInitialized{ false };

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would have dropped the bool and raised an exception if the env variable is not strictly positive.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants