2012-04-03 2 views
1

Я пытаюсь написать код для преобразования массива родного типа C++ в векторный тип соответствующего размера, определенный стандартом OpenCL.Как лучше обрабатывать тип члена класса, который зависит от параметров шаблона?

Endian-ness и упаковка имеют специфическую реализацию OpenCL. Типы OpenCL не обеспечивают удобный оператор []. (на самом деле API - C). Другая проблема: cl_int4 имеет член .s3, но cl_int2 нет.

У меня есть что-то функциональное, но вы можете видеть, что я скитался в сумасшедшей земле.

Можно ли это сделать лучше? Эти функции не будут вызываться часто, поэтому лучше будет сочетанием сокращенного двоичного размера программы и менее длинного исходного кода.

Вот что у меня есть. Я не показываю вам все размерные специализации (опуская 3-6), и я также хотел бы реализовать, по крайней мере, для целочисленного типа.

#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; 
     } 
    } 
}; 

Возможно, вам будет интересно узнать, как я буду использовать этот класс. В одном примере у меня есть шаблон templated для типа REAL, который имеет экземпляр следующего класса-члена, который имеет экземпляр Payload_t.

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() упаковывает OpenCL поддерживается типа таким образом, что я могу послать к API OpenCL в качестве аргумента ядра с всеми байтами падения в нужном месте.

Если кто-то думает о смене парадигмы, мне только понадобится установить весь вектор сразу.

+0

Ссылка на спецификацию типа OpenCL. http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/vectorDataTypes.html – NoahR

ответ

0

Я не уверен, гордиться или стыдиться этого, но он работает. Вам нужно убедиться, что все вызовы set() используют точные правильные типы. Он обрабатывает новые типы cl_ автоматически и новые размеры типов cl_ с изменениями всего в 3 местах. Вероятно, его можно было бы очистить, если бы кто-то почувствовал такую ​​склонность.

#include<iostream> 
#include<assert.h> 

struct cl_float1 { 
    float s0; 
}; 

struct cl_float2 { 
    float s0; 
    float s1; 
}; 


#define ZERO_THROUGH_15(pre) \ 
    pre i0;   \ 
    pre i1;   \ 
    pre i2;   \ 
    pre i3;   \ 
    pre i4;   \ 
    pre i5;   \ 
    pre i6;   \ 
    pre i7;   \ 
    pre i8;   \ 
    pre i9;   \ 
    pre i10;   \ 
    pre i11;   \ 
    pre i12;   \ 
    pre i13;   \ 
    pre i14;   \ 
    pre i15 


template<typename SIMD, typename POD> 
struct offset { 
    static POD SIMD::* data[16]; 
    ZERO_THROUGH_15(static bool); 
    offset() { 
    ZERO_THROUGH_15(); 
    } 
}; 
template<typename SIMD, typename POD> 
/*static*/ POD SIMD::* offset<SIMD,POD>::data[16]; 

template<int n> 
struct offsetGetter { 
    template<typename SIMD, typename POD> 
    static POD SIMD::* get(...) { 
    return NULL; 
    } 
}; 

#define GET_OFFSET(n) \ 
template<> \ 
struct offsetGetter<n> { \ 
    template<typename SIMD, typename POD, POD SIMD::* OFS> \ 
    struct check {}; \ 
\ 
    template<typename SIMD, typename POD> \ 
    static POD SIMD::* get(check<SIMD, POD, &SIMD::s ## n>*) { \ 
    return &SIMD::s ## n; \ 
    } \ 
\ 
    template<typename SIMD, typename POD> \ 
    static POD SIMD::* get(...) { \ 
    return NULL; \ 
    } \ 
    template<typename SIMD, typename POD> \ 
    static bool init() { \ 
    offset<SIMD,POD>::data[n] = get<SIMD,POD>(NULL); \ 
    }; \ 
}; \ 
template<typename SIMD, typename POD> \ 
/*static*/ bool offset<SIMD,POD>::i##n = offsetGetter<n>::init<SIMD,POD>() 

GET_OFFSET(0); 
GET_OFFSET(1); 
GET_OFFSET(2); 
GET_OFFSET(3); 
GET_OFFSET(4); 
GET_OFFSET(5); 
GET_OFFSET(6); 
GET_OFFSET(7); 
GET_OFFSET(8); 
GET_OFFSET(9); 
GET_OFFSET(10); 
GET_OFFSET(11); 
GET_OFFSET(12); 
GET_OFFSET(13); 
GET_OFFSET(14); 
GET_OFFSET(15); 

template<typename SIMD, typename POD> 
void set(SIMD& simd, int n, POD val) { 
    offset<SIMD,POD> ignoreme; 
    POD SIMD::* ofs = offset<SIMD,POD>::data[n]; 
    assert(ofs); 
    simd.*ofs = val; 
} 

main(){ 
    cl_float2 x; 
    set(x, 0, 42.0f); 
    std::cout << x.s0 << std::endl; // prints 42 
    set(x, 1, 52.0f); 
    std::cout << x.s1 << std::endl; // prints 52 
    cl_float1 y; 
    set(y, 1, 42.0f); // assertion failure 
} 
+0

Ничего себе. Я пытался пробиться через это. Несколько нот на данный момент. cl_float1 не является типом OpenCL, это будет cl_float. Я заменил два определения struct на заголовок OpenCL, как в моем примере кода. С этими изменениями я получаю ошибку утверждения из строки 'assert (ofs)' еще до любой строки 'set()' в 'main()'. Я также получаю 80 предупреждений, я думаю, что все, связанные с 'static bool init()' функцией, не возвращаются. Можете ли вы прокомментировать эти два вопроса? – NoahR