c ++ AMP模板特定限制

时间:2015-03-11 10:26:24

标签: c++ templates c++-amp

我在以下代码中遇到了设计问题。我的想法是拥有一个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;
}

我确信有更清洁的方法可以做到这一点,但直到现在我还没找到。

1 个答案:

答案 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类。