为什么在构建C ++ AMP项目期间会出现链接器错误

时间:2014-01-29 15:45:24

标签: c++ c++-amp

我尝试制作一个系统,我需要一个激活器功能。这个激活器函数可能有一个状态,所以我试图将状态放入concurrency :: array_view。当我尝试构建解决方案时,我收到以下链接器错误。

错误2错误LNK2019:未解析的外部符号“public:static double __thiscall ArtNeuroNet :: ActivationFunctions :: Activator :: function(double,class Concurrency :: array_view)restrict(cpu,amp)”(?function @ Activator @ ActivationFunctions @ ArtNeuroNet @@ SENNV?$ array_view @ N $ 00 @ Concurrency @@@ DZ _B)在函数_wmain中引用D:\ Projekte \ ArtNeuroNet \ ArtNeuroNet \ ArtNeuroNet.obj ArtNeuroNet

错误3错误LNK1120:1个未解析的外部D:\ Projekte \ ArtNeuroNet \ Debug \ ArtNeuroNet.exe 1 1 ArtNeuroNet

我的简化激活器看起来像

double Activator::lin_function(double x, concurrency::array_view<double, 1> state)
    restrict(cpu, amp)
{
    if (x > state[StateParameterType::ThresholdParameter])
        return 1;
    else if (x < -(state[StateParameterType::ThresholdParameter]))
        return 0;
    else
        return state[StateParameterType::AlphaParameter] * x + 0.5f;
}

double* Activator::getInitialState(double alpha)
{
    double stateCpu[] = {1.0, 0.5};

    if (alpha != NULL)
        stateCpu[0] = alpha;

    return stateCpu;
}

我的激活器创建看起来像

Activator activator = *(new Activator());
double* stateCpu = activator.getInitialState(1.0);

concurrency::array_view<double, 1> state(2, stateCpu);

activator.lin_function(0.4, state);

出于测试目的,我添加了最后一行,即调用 activator.lin_function(0.4,state)。如果我对该行进行评论,那么项目就会毫无问题地构建。

现在我的问题是,我错过了什么,或者我在做什么,我实际上不应该这样做?

修改

方法lin_function是私有的。但是,在Activator中有一个公共方法函数,它调用私有方法lin_function。出于简化的原因,我将源部分留下了。当对方法lin_function的调用被注释掉时,这两种方法都是可访问的,因为否则我将无法构建解决方案。

Activator完全驻留在同一个项目中,现在是一个控制台应用程序。

lin_function依赖于单个状态变量。但是,激活器功能的阈值实现根本不需要任何状态存储。将所有内容更改为阈值激活功能并对其余内容进行注释会以相同的方式做出反应。特别是“lin_function注释掉 - &gt;没有链接器错误,否则 - &gt;链接器错误“

编辑2

对于Activator,存在标题(Activator.h)和源文件(Activator.cpp)。在某种程度上,链接器似乎无法从标头中找到任何声明为 restrict(cpu,amp)的方法。

// Doesn't get found and throws linker error
double Activator::function(double x)
    restrict(cpu, amp)
{
    return (x >= 0) ? 1 : 0;
}

// Get's found and no linker errors occur
double Activator::function(double x)
{
    return (x >= 0) ? 1 : 0;
}

编辑3

在头文件中将包含restrict(amp,cpu)的所有方法定义为静态后,所有内容都正确构建并且运行没有问题。

当使用restrict(amp,cpu)时,是否存在对静态方法的限制?

1 个答案:

答案 0 :(得分:0)

以下是C ++ AMP在类和函数等方面的限制。您也仅限于受支持的C ++类型的子集,但我认为这不是问题。

  

引用和指针(兼容类型)可以在本地使用,但是   不能被lambda捕获。功能指针,   不允许指针指针等;都不是静止的   或全局变量。

     

如果您希望使用它们的实例,则必须满足更多规则。   它们必须没有虚函数或虚继承。   允许构造函数,析构函数和其他非虚函数。   成员变量必须都是兼容的类型,可以是   当然包括其他类的实例,只要这些类   符合相同的规则。放大器兼容功能中的实际代码   没有在CPU上运行,因此不能做你的某些事情   可能习惯了:

     
      
  • 递归
  •   
  • 指针转换
  •   
  • 使用虚拟功能
  •   
  • new或delete
  •   
  • RTTI或动态投射
  •   
  • 转到
  •   
  • 扔,尝试或抓住
  •   
  • 访问全局或静态
  •   
  • 内联汇编程序
  •   

这是从我的书中提取的,我道歉,因为它有误导性。尚不清楚的是,这适用于您希望作为数据传递给AMP内核的类。不要对其上有restrict(amp)方法的类。这仅适用于静态方法,因为它无法与GPU共享类this指针,因为它引用了CPU上的对象实例。

以下是满足上述要求并可以传递给AMP内核的类的示例:

class stuff
{
public:
    int a;

    stuff(int v) : a(v) { }
};

stuff也符合受支持类型的要求,因为AMP支持int

以下课程在stuff中使用array_view

class test_case
{
public:
    test_case()
    {
    }

    static int amp_method(int a) restrict(amp, cpu)
    {
        return a * a;
    };

    void test_amp()
    {
        concurrency::array_view<stuff, 1> data(100);
        concurrency::parallel_for_each(data.extent, 
            [data](concurrency::index<1> idx) restrict(amp)
        {
            data[idx].a = amp_method(data[idx].a);
        });
        data.synchronize();
    };

    void test_cpu()
    {
        std::vector<int> data(100, 0);
        for (auto& d : data)
        {
            d = amp_method(d);
        }
    }
};

如果删除static上的amp_method修饰符,则会在VS 2013上收到以下错误。

  

警告C4573:'test_tools_tests :: test_case :: amp_method'的用法   要求编译器捕获this但是当前默认值   捕获模式不允许它

你可能会在2012年看到不同的东西。第一个AMP版本的缺点之一是它的错误。这在2013年有所改善。

反思这一切看起来都很合理。当它引用CPU上运行的代码时,如何将this传递给GPU?

请注意,restrict无法应用于类。

感谢您突出显示此问题。我想我应该更新本书勘误表。