Ich versuche, Code zu schreiben, um ein Array eines nativen C++ - Typs in einen Vektor mit geeigneter Größe zu konvertieren, der vom OpenCL-Standard definiert wird.Wie kann ein Klassenmembertyp, der von Vorlagenparametern abhängt, besser behandelt werden?
Endian-Ness und Packing sind OpenCL-spezifische Implementierung. Die OpenCL-Typen bieten keinen praktischen Operator []. (eigentlich ist die API C) Ein weiteres Problem: cl_int4
hat eine .s3
Mitglied, aber cl_int2
nicht.
Ich habe etwas, das funktionell funktioniert, aber Sie können sehen, dass ich in das Land der Schablone verrückt gegangen bin.
Kann dies besser gemacht werden? Diese Funktionen werden nicht oft aufgerufen, daher wäre besser eine Kombination aus reduzierter Programmbinärgröße und weniger langem Quellcode.
Hier ist, was ich bisher habe. Ich zeige Ihnen nicht alle dimensionalen Spezialisierungen (3-6 weglassen), und ich möchte auch für mindestens den Integer-Typ auch implementieren.
#include <CL/cl.h>
template < typename HOST_T, int NUM_DIM >
struct Payload_t;
// Vector length needs to be (for dims 1-6): 2, 4, 8, 8, 16, 16
//single precision
template < >
struct __attribute__((packed)) Payload_t <float, 1> {
cl_float2 vec;
void setElement(int pos, float value)
{
switch (pos) {
case 0: vec.s0 = value; return;
case 1: vec.s1 = value; return;
default: return;
}
}
};
template < >
struct __attribute__((packed)) Payload_t <float, 2> {
cl_float4 vec;
void setElement(int pos, float value)
{
switch (pos) {
case 0: vec.s0 = value; return;
case 1: vec.s1 = value; return;
case 2: vec.s2 = value; return;
case 3: vec.s3 = value; return;
default: return;
}
}
};
/// double-precision
template < >
struct __attribute__((packed)) Payload_t <double, 1> {
cl_double2 vec;
void setElement(int pos, double value)
{
switch (pos) {
case 0: vec.s0 = value; return;
case 1: vec.s1 = value; return;
default: return;
}
}
};
template < >
struct __attribute__((packed)) Payload_t <double, 2> {
cl_double4 vec;
void setElement(int pos, double value)
{
switch (pos) {
case 0: vec.s0 = value; return;
case 1: vec.s1 = value; return;
case 2: vec.s2 = value; return;
case 3: vec.s3 = value; return;
default: return;
}
}
};
Ich denke, Sie könnten neugierig sein, wie ich diese Klasse verwenden würde. In einem Beispiel habe ich eine Klasse, die auf den Typ REAL templatiert ist und eine Instanz der folgenden Mitgliedsklasse hat, in der eine Instanz der Payload_t
enthalten ist.
template <int NUM_DIM >
struct cartesian_box_descriptor_t : cartesian_box_descriptor_base_t
{
static const int vectorLengthArray[6];
void set_dx(REAL * dx_vec)
{
for (int i = 0; i < NUM_DIM; ++i)
payload.setElement(i, dx_vec[i]);
};
void set_startx(REAL * startx_vec)
{
for (int i = 0; i < NUM_DIM; ++i)
payload.setElement(NUM_DIM + i , startx_vec[i]);
};
virtual WxAny getDescriptorStruct() const
{
return WxAny(payload); // packages this simple structure as 'scalar' with hidden type
};
Payload_t< REAL, NUM_DIM> payload;
};
getDescriptorStruct()
Die Pakete der OpenCL unterstützten Typ in einer Weise, die ich zur OpenCL API als Kernel-Argument mit allen Bytes fallen an der richtigen Stelle senden.
Wenn jemand über einen Paradigmenwechsel nachdenkt, muss ich immer nur den gesamten Vektor auf einmal einstellen.
Link zur OpenCL-Vektortypspezifikation. http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/vectorDataTypes.html – NoahR