CUDA는 가상 함수가있는 클래스가 커널 함수로 전달되는 것을 허용하지 않습니다. 이 제한 사항에 대한 해결 방법이 있습니까?장치 측 CUDA 가상 함수를 구현하는 방법은 무엇입니까?
커널 기능 내에서 다형성을 사용하고 싶습니다.
감사합니다.
CUDA는 가상 함수가있는 클래스가 커널 함수로 전달되는 것을 허용하지 않습니다. 이 제한 사항에 대한 해결 방법이 있습니까?장치 측 CUDA 가상 함수를 구현하는 방법은 무엇입니까?
커널 기능 내에서 다형성을 사용하고 싶습니다.
감사합니다.
로버트 Crovella의 코멘트의 가장 중요한 부분은 다음과 같습니다
객체는 단순히 디바이스에 생성 될 필요가있다.
그런 점을 염두에 두면서, 나는 추상적 인 class Function
을 가진 상황을 다루었으며, 그 다음에 다른 기능과 평가를 캡슐화 한 일부 구현을 다루었습니다.
class Function
{
public:
__device__ Function() {}
__device__ virtual ~Function() {}
__device__ virtual void Evaluate(const real* __restrict__ positions, real* fitnesses, const SIZE_TYPE particlesCount) const = 0;
};
class FunctionRsj : public Function
{
private:
SIZE_TYPE m_DimensionsCount;
SIZE_TYPE m_PointsCount;
real* m_Y;
real* m_X;
public:
__device__ FunctionRsj(const SIZE_TYPE dimensionsCount, const SIZE_TYPE pointsCount, real* configFileData)
: m_DimensionsCount(dimensionsCount),
m_PointsCount(pointsCount),
m_Y(configFileData),
m_X(configFileData + pointsCount) {}
__device__ ~FunctionRsj()
{
// m_Y points to the beginning of the config
// file data, use it for destruction as this
// object took ownership of configFilDeata.
delete[] m_Y;
}
__device__ void Evaluate(const real* __restrict__ positions, real* fitnesses, const SIZE_TYPE particlesCount) const
{
// Implement evaluation of FunctionRsj here.
}
};
__global__ void evaluate_fitnesses(
const real* __restrict__ positions,
real* fitnesses,
Function const* const* __restrict__ function,
const SIZE_TYPE particlesCount)
{
// This whole kernel is just a proxy as kernels
// cannot be member functions.
(*function)->Evaluate(positions, fitnesses, particlesCount);
}
__global__ void create_function(
Function** function,
SIZE_TYPE dimensionsCount,
SIZE_TYPE pointsCount,
real* configFileData)
{
// It is necessary to create object representing a function
// directly in global memory of the GPU device for virtual
// functions to work correctly, i.e. virtual function table
// HAS to be on GPU as well.
if (threadIdx.x == 0 && blockIdx.x == 0)
{
(*function) = new FunctionRsj(dimensionsCount, pointsCount, configFileData);
}
}
__global__ void delete_function(Function** function)
{
delete *function;
}
int main()
{
// Lets just assume d_FunctionConfigData, d_Positions,
// d_Fitnesses are arrays allocated on GPU already ...
// Create function.
Function** d_Function;
cudaMalloc(&d_Function, sizeof(Function**));
create_function<<<1, 1>>>(d_Function, 10, 10, d_FunctionConfigData);
// Evaluate using proxy kernel.
evaluate_fitnesses<<<
m_Configuration.GetEvaluationGridSize(),
m_Configuration.GetEvaluationBlockSize(),
m_Configuration.GetEvaluationSharedMemorySize()>>>(
d_Positions,
d_Fitnesses,
d_Function,
m_Configuration.GetParticlesCount());
// Delete function object on GPU.
delete_function<<<1, 1>>>(d_Function);
}
이것은 내가 찾고있는 것입니다. 고맙습니다!! 하나의 후속 질문 : 커넬이나 디바이스 함수 내에서'new' 또는'malloc'를 거대한 퍼포먼스에 부딪 히지 않는 것입니까? – Acerebral
@Acerebral 잘 제 경우에는 어떤 중요한 오버 헤드를 경험하지 못했습니다. 그리고 모든 문제를 해결하는 방법을 더 잘 상상할 수 없으므로 malloc 또는 new가 성능을 해칠지라도 나는별로 신경 쓰지 않을 것입니다. 추상 클래스가없는 단순한 접근법과 비교해 보았습니다. CPU에 함수를 만들고 'cudaMemcpy'를 사용했지만 성능은 거의 같았습니다. 솔루션을 구현하고 필요한 경우에만 최적화하는 것 같습니다. –
당신은 내 다형성을 사용할 수 있습니다 : 그것은 희망 아이디어를 얻을하는 데 도움이됩니다 ... 이것은 내가 내 상황에서 다형성을 달성하는 방법을 내 코드의 단순화 된 버전입니다,하지만 난 그게 더 할 수없는 말을하고 있지 않다 CUDA 커널 기능. 객체는 단순히 장치에서 만들어야합니다. 호스트에서 가져온 데이터로 객체를 초기화해야하는 경우에도 일반적으로 그렇게하기가 어렵지 않습니다. 나는 응답 [여기] (http://stackoverflow.com/questions/22988244/polymorphism-and-derived-classes-in-cuda-cuda-thrust/23476510?s=2|1.7036#23476510)을 보여 주며 개념을 보여줍니다. 추력으로, 물론 일반 CUDA 코드에서도 작동하도록 만들 수 있습니다. –
@Robert Crovella이 문제의 원인은 장치에 고유 한 가상 함수 테이블의 주소입니다. 객체가 장치간에 이동하는 다중 gpu 응용 프로그램에 어떤 영향이 있습니까? 전의. 장치 0에 다형성 클래스를 인스턴스화 한 다음 장치 1에 인스턴스를 memcpy (동일한 클래스의 인스턴스가있는 경우)합니다. 그 객체가 memcopied 객체를 깨뜨릴 것입니까, 아니면 디바이스 1의 가상 함수 테이블을 완벽하게 사용합니까? – Acerebral
나는 그것을 기대하지 않을 것이다. 가상 함수 표는 기본적으로 포인터 집합입니다. 이러한 포인터 (주소)는 호출하려는 장치에 대해서만 정확할 것입니다. 사실 UVA가 제대로 작동하지 않을 것이라고 보장 할 수있을 것으로 기대합니다. 비 UVA 설정에서 작동하도록 할 수는 있지만 그다지 믿을 수는 없습니다. 그러나 나는 단지 여기에서 추측하고있다. 나는 그것을 직접 시도하지 않았다. –