我可以根据C ++中的运行时条件定义类型别名吗?

时间:2011-05-21 13:35:52

标签: c++ opencl

我正在开发一个OpenCL程序,它使用“cl_khr_byte_addressable_store”扩展来允许在内核代码中进行字节级写入;为了使我的程序也可以在不支持扩展的GPU上工作,我需要检查扩展是否可用,并在不适用的平台上使用int类型而不是char

在内核代码中,我只需添加以下代码段并在整个内核代码中使用writeable_type;如果扩展可用,则OpenCL内核编译器会自动添加预处理器定义cl_khr_byte_addressable_store

/* kernel.cl */
#ifdef cl_khr_byte_addressable_store
    typedef char writeable_type;
#else
    typedef int writeable_type;
#endif

f() {
    writeable_type x = 1;
}

在我的主机代码中,我没有那个预处理器定义,并且(据我所知)检查扩展是否可用只能在运行时完成:

/* host.cpp */
void execute() {
    std::string extensions;
    this->opencl->getExtensions(extensions);
    if (extensions.find("cl_khr_byte_addressable_store") != std::string::npos) {
        // extension is available
        typedef cl_char writeable_type;
    }
    else {
        // extension is not available
        typedef cl_int writeable_type;
    }
    writeable_type x = 1;
}

那是我的问题;因为typedef在编译时被解析并且仅在定义它们的块内有效,所以上面的示例不起作用。

有可能以某种方式这样做吗?


感谢rlc,Neil Butterworth和talonmis让我走上了正确的道路!我的问题的解决方案变得相当简单:

/*host.cpp*/

void execute() {
   bool extension_available = ...;  
   if (extension_available)
       this->_execute<cl_char>();
   else
       this->_execute<cl_int>();
}

template <typename writeable_char>
void _execute() {
    writeable_type x = 1;
    // ...
}

4 个答案:

答案 0 :(得分:2)

如果您的所有代码都在公共函数与该类型无关的类中,您可以执行以下操作:

// assuming these are defined in OpenCL somewhere
typedef char cl_char;
typedef int cl_int;

// the public part of the base class cannot use the 
// writable size because it cannot know the size of the writable type
class Base
{
public :
    /* stuff */
    virtual void doStuff() = 0;
    /* more stuff */
};

// the writable type's size is known in this class and is
// either cl_char or cl_int, so this is where data that has
// to know the size will be carried around, and where API calls
// that need to know the exact writable type go.
// Code that is agnostic of the writable type need not be here
// (but can be)
template < typename WritableType >
class Derived : public Base
{
public :
    virtual void doStuff()
    {
        /* do stuff */
    }
};

int main()
{
    bool condition(false);
    /* magic to check for type size here */
    // once you get here, you know what the writable type is going to be,
    // so you can create an instance of the derived class accordingly
    Base *o;
    if (condition)
    {
        o = new Derived< cl_char >;
    }
    else
    {
        o = new Derived< cl_int >;
    }
    // as of here, you no longer need to know what the writable type
    // is because that knowledge is encapsulated in the object o
    o->doStuff();
}

即。模板根据运行时所需的类型执行所有操作的类,并使用您需要的版本。

答案 1 :(得分:1)

C ++中的所有类型必须在编译时才知道 - 此规则没有例外(C也是如此)。并且考虑到定义语言的方式,尝试在运行时重新定义类型根本没有意义。如果您发现自己认为需要这样做,那么您的设计就会出现问题。

答案 2 :(得分:1)

您必须对目标OpenCL平台使用的选项进行运行时检查并做出相应的反应。使用clGetPlatformInfo查询调用CL_PLATFORM_EXTENSIONS,您将获得一个字符数组,可以对其进行解析以检查是否支持cl_khr_byte_addressable_store。然后相应地选择具有整数或字符类型的路径。

大多数供应商SDK都包含某种设备查询应用程序,其中包含clGetPlatformInfo用法的示例。你应该能够从那里获得一些代码。

答案 3 :(得分:0)

您尝试在编译时更改变量,具体取决于运行时某些值。除非你把编译时间带到运行时,例如JIT或解释,或发明时间旅行,否则物理定律决定了你想要的东西是不可能的。

当然,您也可以使用继承和虚函数来删除依赖项。