我在以下代码中遇到了设计问题。我的想法是拥有一个Data类,它有两个嵌套类GPU和Process。 GPU包含传输到GPU ...和Process的数据,在CPU和GPU上使用相同的代码处理数据。
#include <amp.h>
class Data
{
public:
template <class DataToProcess>
class Process
{
public:
Process(const DataToProcess &pp): p(pp){};
// Here is the problem ... I want operator() to be restrict(amp) if DataToProcess is Data::GPU and restrict(cpu) if DataToProcess is Data
float operator()() const restrict(amp, cpu)
{ // do stuff
}
private:
DataToProcess p;
};
class GPU
{
public:
// Constructor transfers vectors and other datas to GPU
GPU(Data& host) : d(host.d), f(host.f){}
const Process<Data::GPU> getProcessor() const { return Data::Process<Data::GPU>(*this); }
public:
concurrency::array_view<float> d;
float f;
};
public:
Data(){}
const Process<Data> getProcessor() const { return Process<Data>(*this); }
GPU TransferToGPU()
{
// Construct the gpu object
GPU gpu(*this);
// Returns it
return gpu;
}
public:
std::vector<float> d;
float f;
};
int main(int argc, char* argv[])
{
Data d;
Data::GPU dgpu = d.TransferToGPU();
auto p1 = d.getProcessor();
auto p2 = dgpu.getProcessor();
return 0;
}
我现在停留在operator()的定义上,因为我将它应用于Data,它需要restrict(cpu),当我将它应用于Data :: GPU时,它需要restrict(amp)。
有没有可能使它有效?
我在AMP文档中读到有一天会出现限制(自动)。我认为这符合我的需要。
修改
感谢ForEveR,对于那些感兴趣的人,我找到了一个解决方案,我觉得很脏。但这符合我的需要。
我的想法是使用SFINAE作为指向ForEveR,但是要在旧样式宏中定义它们,以便我可以在使用此结构的所有类中使用它。
以下是代码:
#define MyOperator( compute_method ) \
template< typename = typename std::enable_if<std::is_same<DataToProcess, Data>::value>::type>\
float operator()() const restrict(cpu)\
{\
compute_method \
}\
template< typename = typename std::enable_if<std::is_same<DataToProcess, Data::GPU>::value>::type>\
float operator()() const restrict(amp)\
{\
compute_method\
}
class Data
{
public:
class GPU;
template <class DataToProcess>
class Process
{
public:
Process(const DataToProcess &pp)
: p(pp)
{
};
MyOperator(
int ab = 0;
return ab;
)
private:
DataToProcess p;
};
class GPU
{
public:
// Constructor transfers vectors and other datas to GPU
GPU(Data& host)
: d(host.d)
, f(host.f)
{}
const Process<Data::GPU> getProcessor() const { return Data::Process<Data::GPU>(*this); }
public:
concurrency::array_view<float> d; //< The different stacks of medium
float f; //< The current frequency being processed by the stacks
};
public:
Data(){}
const Process<Data> getProcessor() const { return Process<Data>(*this); }
GPU TransferToGPU()
{
// Construct the gpu object
GPU gpu(*this);
// Returns it
return gpu;
}
// ------------------------------------------------
// Private members
// ------------------------------------------------
public:
std::vector<float> d; //< The different stacks of medium
float f; //< The current frequency being processed by the stacks
};
int main(int argc, char* argv[])
{
Data d;
Data::GPU d_gpu = d.TransferToGPU();
auto p = d.getProcessor();
auto p_gpu = d_gpu.getProcessor();
p();
p_gpu(); // This line does not compile as p_gpu is amp restricted, that is what we want
return 0;
}
我确信有更清洁的方法可以做到这一点,但直到现在我还没找到。
答案 0 :(得分:0)
你可以在C ++ 11中使用带有type_traits的SFINAE来做这样的事情。
typename std::enable_if<std::is_same<DataToProcess, Data>::value, float>::type
operator()() const restrict(cpu)
{
// do stuff
}
typename std::enable_if<std::is_same<DataToProcess, Data::GPU>::value, float>::type
operator()() const restrict(amp)
{
// do stuff
}
不要忘记转发声明GPU
类。