我正在开发一个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;
// ...
}
答案 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或解释,或发明时间旅行,否则物理定律决定了你想要的东西是不可能的。
当然,您也可以使用继承和虚函数来删除依赖项。