So I know that it is possible to use custom types with OpenCL. But I haven't been able to use them with VexCL. Creating a device vector of structs works fine, but I can't perform any operations.
As I haven't found any examples using custom types with VexCL my question is is that even possible? Thanks in advance.
VexCL does not support operations with vectors of structs out of the box. You will need to help it a bit. First, you need to tell VexCL how to spell the type name of the struct. Let's say you have the following struct defined on the host side:
struct point2d {
double x;
double y;
};
You need to provide a specification of the vex::type_name_impl struct that will generate a string corresponding to the type name of the struct. Remember that the code you are generating is C99:
namespace vex {
template <> struct type_name_impl<point2d> {
static std::string get() { return "struct point2d"; }
};
}
You will also need to make sure every generated kernel knows about your struct. This may be achieved with vex::push_program_header() function after the VexCL context has been initialized:
vex::push_program_header(ctx, "struct point2d { double x; double y; };");
This will allow you to declare vectors of the struct, and to pass the vectors to custom functions. That should be general enough. Here is the complete example:
#include <vexcl/vexcl.hpp>
// Host-side definition of the struct.
struct point2d {
double x, y;
};
// We need this for code generation.
namespace vex {
template <>
struct type_name_impl<point2d> {
static std::string get() { return "struct point2d"; }
};
}
int main() {
const size_t n = 16;
vex::Context ctx(vex::Filter::Env);
std::cout << ctx << std::endl;
// After this, every kernel will have the struct declaration in header:
vex::push_program_header(ctx, "struct point2d { double x; double y; };");
// Now we may define vectors of the struct:
vex::vector<point2d> x(ctx, n);
vex::vector<double> y(ctx, n);
// We won't be able to use the vectors in any expressions except for
// custom functions, but that should be enough:
VEX_FUNCTION(point2d, init, (double, x)(double, y),
struct point2d p = {x, y}; return p;
);
VEX_FUNCTION(double, dist, (point2d, p),
return sqrt(p.x * p.x + p.y * p.y);
);
x = init(3,4);
y = dist(x);
std::cout << y << std::endl;
}
And here is the kernel that will be generated for the assignment operation of y = dist(x);:
struct point2d { double x; double y; };
double dist
(
struct point2d p
)
{
return sqrt(p.x * p.x + p.y * p.y);
}
kernel void vexcl_vector_kernel
(
ulong n,
global double * prm_1,
global struct point2d * prm_2
)
{
for(ulong idx = get_global_id(0); idx < n; idx += get_global_size(0))
{
prm_1[idx] = dist( prm_2[idx] );
}
}
Related
I'm looking to build a 1D std::array of structs, each of whose size is 16 bytes. The 1D array is a flattening of a class representing a 3D array (basically an std::array wrapper that has some 3D specific operators and other fluff). My first attempt is an array of size 256 x 256 x 32, so roughly 35MB, which throws a SIGSEGV error.
A simplified example of everything looks like this:
Structs.cpp
struct Coord {
int x;
int y;
int z;
Coord() { }
Coord(int x_, int y_, int z_) { x = x_; y = y_; z = z_; }
}
int TR (int arg) {
// ... Some transformation
}
struct MyStruct {
Coord position;
int terrain;
MyStruct() { }
MyStruct(int x_, int y_, int z_, int terrain_) {
terrain = terrain_;
position = Coord(TR(x_), TR(y_), TR(z_));
}
}
ArrayWrapper.hpp
#include <array>
template <typename T, int HSIZE, int VSIZE> struct ArrayWrapper {
private:
std::array<T, HSIZE*HSIZE*VSIZE> narray;
public:
void set(T obj, int x, int y, int z) {
narray[x + z*HSIZE + y*HSIZE*HSIZE] = obj;
}
T& operator() (int x, int y, int z) {
return narray.at(x + z*HSIZE + y*HSIZE*HSIZE);
}
CoordinateMap.cpp
#include "ArrayWrapper.hpp"
#include "Structs.cpp"
const int HSIZE = 256;
const int VSIZE = 32;
class CMap {
private:
ArrayWrapper<MyStruct, HSIZE, VSIZE>* coords_ = new ArrayWrapper<MyStruct, HSIZE, VSIZE>;
ArrayWrapper<MyStruct, HSIZE, VSIZE> coords = *coords_;
public:
// ... Getter, setter, and a bunch of other methods,
~CMap() { delete coords; }
}
If I anywhere try to say CMap something; I get a SIGSEGV. I know that the stack is relatively small, so I'm attempting to allocate this structure on the heap by using new. Many people (on this site and others) say "Finding a large range of contiguous memory is difficult, even if it's on the heap," but don't give an indication of what a reasonable expectation of the size of contiguous memory is. I would think 32MB in a modern-day computer is doable.
What might be throwing a Seg. fault here?
ArrayWrapper<MyStruct, HSIZE, VSIZE> coords = *coords_;
Should be...
ArrayWrapper<MyStruct, HSIZE, VSIZE>& coords = *coords_;
... which makes sense. The 1st line is making a copy of coords_' reference, which, in this case, defeats the purpose of using new, since that copy is put on the stack.
Can I pass an array (contactsLonN ..) of a class that is within/or a subcomponent of an array of classes (chainref) to a function in C++?
// ChainNetwork.cpp
void build_contact_map(Chain *chain, int num_chains,Contact *map) {
//accept 1 of contactsLonN, contactsLonS, contactsLatW, contactsLatE;
}
// ChainNetwork.h
class Vector {
public:
double x;
double y;
double z;
Vector (); // Constructor declared.
};
inline Vector::Vector() {
x = 0.0;
y = 0.0;
z = 0.0;
}
class Contact {
public:
int cresid;
double distance;
Contact (); // Constructor declared.
};
inline Contact::Contact() {
cresid = -1;
distance = 0.0;
}
class ChainNetwork {
public:
struct Contact contactsLonN[1000][20];
struct Contact contactsLonS[1000][20];
struct Contact contactsLatW[1000][20];
struct Contact contactsLatE[1000][20];
}
// declarations in ChainNetwork.h
void build_contact_map(ChainNetwork *chain, int num_chains,Contact *map);
double distance ( Vector v1, Vector v2 );
// main.cpp main()
ChainNetwork *chainref;
try {
chainref = new ChainNetwork [num_chains];
} catch (std::bad_alloc xa) {
std::cout << "Allocation Failure\n";
return 1;
}
// 1 generic function I would like to call .. but seems to grow uncontrollably if I try to use switch(s)
build_contact_map(chainref,chains_to_use,chainref[i].contactsLonN);
build_contact_map(chainref,chains_to_use,chainref[i].contactsLonS);
build_contact_map(chainref,chains_to_use,chainref[i].contactsLatW);
build_contact_map(chainref,chains_to_use,chainref[i].contactsLatE);
Note: Related results usually employed simpler structures like ints, float, or struct, but not an array or double index array of a class within a class.
Note2: I have made extensive use of functions receiving "Vector" correctly, by reference or address; how about contactsLonN ..
Contact[1000][20] cannot be converted to Contact*; they are different types. You could change build_contact_contact_map() to accept Contact (*map)[20], or, better yet, use a std::vector<std::vector<Contact>> instead of raw arrays.
I have this code:
class Vector3
{
public:
Vector3() : x(values[0]), y(values[1]), z(values[2])
{ x = y = z = 0; }
float& x;
float& y;
float& z;
private:
float[3] values;
};
class Model
{
public:
Vector3 vertices[64];
};
I'm doing this vector class because I want to deal with the values as X, Y, Z in the code, but for some operations I need a contiguous array of values to be passed to a function.
So the whole array of vertices[64] need to be [x0][y0][z0][x1][y1][z1][x2][y2][z2] etc.
But if I do this:
//Get first address:
void* firstAddress = &vertices[0];
//Or
void* firstAddress = vertices;
I don't have the contiguous array as I need it (the data is all messed up), and I'm guessing it's because of the pointers I have in the Vector3 class.
Is there any way I can do get this functionality that I want? (Having a single array of float but dealing with values as x,y,z)
Firstly, the Standard doesn't define how references should be implemented, but they'll almost certainly occupy actual memory in your class much a pointer members would, ruining the contiguous data packing you're hoping for....
If your focus is more on the vertices container, and you just want x/y/z member access to elements in it, then you could try something like:
template <size_t N>
class Vertices
{
public:
class Proxy
{
public:
Proxy(float* p) : x(p[0]), y(p[1]), z(p[2]) { }
float& x;
float& y;
float& z;
};
Proxy operator[](size_t n) { return Proxy(&d_[n * 3]); }
const Proxy operator[](size_t n) const { return Proxy(&d_[n * 3]); }
private:
float d_[N * 3];
};
You could have member functions instead:
class V3
{
float data[3];
public:
V3() : data{0,0,0} {}
float & x() { return data[0]; }
float & y() { return data[1]; }
float & z() { return data[2]; }
};
You could also omit the constructor and have an aggregate, if that's more suitable.
What you have and array of values pointers (pointing to arrays of 3 floats) with 3 float references (x, y, z). You probably ant something more like:
float & x() { return values[0]; }
float & y() { return values[1]; }
float & z() { return values[2]; }
If I understand your requirement for continuous data in the Model, then your Vector is really an alias to a specific triple of data in the model. No float storage required.
class Model
class Vector
Vector(Model *model_, size_t idx_) : model(model_),idx(idx_) { };
Model *model;
size_t idx;
float & x() { return model->data[3*idx]; }
float & y() { return model->data[3*idx+1]; }
float & z() { return model->data[3*idx+2]; }
float data[64 * 3];
Vector vectors[64];
Model() {
...
for( size_t ii = 0; ii < 64; ii++ ) {
vectors[ii] = new Vector(this,ii);
}
Vector & vector(size_t idx) { return vectors[ii]; }
For a guaranteed contiguous array you need to either copy the data into the array, or use compiler-specific guarantees about memory layout, in particular that
there will be no padding,
and if you want to also access triplets of the array as Vector3 instances, that
accessing a Vector3 at arbitrary address will not cause a trap or inefficiency (we're into alignment here).
It so happens that some common libraries such as OpenCV do make such assumptions for their internal image buffers.
But I'm not entirely sure that the code I've seen has not been platform-adapted. So, in practice you have these choices:
copy the data contiguously to an array (or from it), and/or
use an existing library that provides this kind of functionality, such as OpenCV.
Note that using member functions instead of references buys you nothing wrt. to the contiguous array problem, but it does make the Vector3 potentially assignable.
On further reflection, i was maybe too trigger-happy writing the above. For if you can guarantee total size 3*sizeof(float), and that's almost a given (just get rid of those references), then you are guaranteed that you can access a Vector3 at any address that can hold a float, since C++ guarantees arrays with no padding, and since in such an array a Vector3 can end up at any address that can hold a float. So the in-practice problem reduces to making a decision about supporting compilers or compiler configurations that are unable to make Vector3 of size 3*sizeof(float).
I.e.
struct Vector3
{
float x, y, z;
auto operator[]( int i ) -> float& { return (&x)[i]; }
auto operator[]( int i ) const -> float const& { return (&x)[i]; }
};
static_assert( sizeof( Vector3 ) == 3*sizeof( float ), "Ungood Vector3 size" );
using the fact that members with no intervening access specifier are guaranteed to be in increasing address order.
Disclaimer: off the cuff code, not touched by compiler's hands.
If you keep your Vector3 class a POD you should be able to simply cast your vertices to a float array:
struct Vector3 {
float x;
float y;
float z;
};
class Model
{
public:
Vector3 vertices[64];
float* data() {
return reinterpret_cast<float*>(vertices);
}
};
int main() {
Model m;
for(int i = 0; i < 64; ++i) {
m.vertices[i] = {10+i,100+i,1000+i};
}
float *data = m.data();
for(int i= 0; i < 64*3; ++i) {
std::cout << data[i] << ", ";
}
}
Only problem could be the Allignment of the structure, but should you use c++11, there is a standard way of alligning the structure, using allignasalignas(alignof(float[3])). I don't know if this is really required.
Also, c++11 gives quite a few options on what to do with Vector3, while still considering it as a POD type.
Is it possible in C++ to refer to the same variable using different names without using the preprocessor?
To achieve the same effect as this pseudocode
struct vec3f {
float[3] values;
};
struct color : public vec3f {
#define r values[0]
#define g values[1]
#define b values[2]
};
color c;
c.r = 0.5f;
The following has the right semantics except it allocates space in the struct for the 3 references:
struct color : public vec3f {
float& r;
float& g;
float& b;
color() : r(values[0]), g(values[1]), b(values[2]) { }
};
Is there a way to get this compile-time name substitution without increasing the size of the struct?
How about this?
struct vec3f {
float[3] values;
};
struct color : public vec3f
{
float& r() { return values[0]; }
float& g() { return values[1]; }
float& b() { return values[2]; }
const float& r() const { return values[0]; }
const float& g() const { return values[1]; }
const float& b() const { return values[2]; }
};
I am not sure that you want to use inheritance in this case. You might be better of with a plain old union type:
typedef float vec3f[3];
union color {
vec3f values;
struct {
float r;
float g;
float b;
};
};
color c;
c.values[0] = 10;
assert( c.r == 10 );
As it happens, I first saw a really neat trick for this several years ago.
The idea is that you give the class named variables in order, and then also have a static const member of array-of-pointer-to-member type. The operator[] is overloaded to look up the appropriate pointer-to-member, use it to select the member from this, and return a reference.
This works because pointer-to-members are not ordinary pointers; they're a little more magical than that. (This is what enables you to create un-bound pointers to member functions, and why they can't be used where plain function pointers are expected).
It also means that you don't have to use any casting tricks, rely on any kinds of alignment, non-portable anonymous-union behaviour, or memory layout guarantees, and you still get to refer to the components of the structure as named fields instead of via accessor functions.
ALTERNATIVE 1
You always create a temporary when you want a variable alias. With a good optimizer you will hardly see any performance difference.
struct vec3f
{
float values[3];
};
struct tempvec
{
float &r;
float &g;
float &b;
tempvec( vec3f& bar )
:r(bar.values[0])
, g(bar.values[1])
, b(bar.values[2]){}
};
int main()
{
vec3f temp;
temp.values[0] = 2.40f;
//when you want to alias values[0] as r do this
tempvec(temp).r = 42;
tempvec(temp).g = 42;
return 0;
}
ALTERNATIVE 2
If you can verify that memory layout of vec3f and vec3c is the same on your platform and OS.. taking into account padding/alignment etc... you can do
struct vec3f
{
float values[3];
};
struct vec3c
{
float r,g,b;
};
int main()
{
vec3f temp;
temp.values[0] = 2.40f;
vec3c* alias = reinterpret_cast<vec3c*>(&temp);
alias->r = 4.2f;
alias->g = 4.2f;
alias->b = 4.2f;
return 0;
}
There's no way to do something like this, in C++ is there?
union {
{
Scalar x, y;
}
Scalar v[2];
};
Where x == v[0] and y == v[1]?
Since you are using C++ and not C, and since they are of the same types, why not just make x a reference to v[0] and y a reference to v[1]
How about
union {
struct {
int x;
int y;
};
int v[2];
};
edit:
union a {
struct b { int first, second; } bee;
int v[2];
};
Ugly, but that's more accurate
Try this:
template<class T>
struct U1
{
U1();
T v[2];
T& x;
T& y;
};
template<class T>
U1<T>::U1()
:x(v[0])
,y(v[1])
{}
int main()
{
U1<int> data;
data.x = 1;
data.y = 2;
}
I've used something like this before. I'm not sure its 100% OK by the standard, but it seems to be OK with any compilers I've needed to use it on.
struct Vec2
{
float x;
float y;
float& operator[](int i) { return *(&x+i); }
};
You can add bounds checking etc to operator[] if you want ( you probably should want) and you can provide a const version of operator[] too.
If you're concerned about padding (and don't want to add the appropriate platform specific bits to force the struct to be unpadded) then you can use:
struct Vec2
{
float x;
float y;
float& operator[](int i) {
assert(i>=0);
assert(i<2);
return (i==0)?x:y;
}
const float& operator[](int i) const {
assert(i>=0);
assert(i<2);
return (i==0)?x:y;
}
};
I was looking for a similair thing and eventually came up with a solution.
I was looking to have a data storage object that I could use as both an array of values and as individual values (for end-user flexibility in writing Arduino libraries).
Here is what I came up with:
class data{
float _array[3];
public:
float& X = _array[0];
float& Y = _array[1];
float& Z = _array[2];
float& operator[](int index){
if (index >= 3) return _array[0]; //Make this action whatever you want...
return _array[index];
}
float* operator&(){return _array;}
};
int main(){
data Test_Vector;
Test_Vector[0] = 1.23; Test_Vector[1] = 2.34; Test_Vector[2] = 3.45;
cout<<"Member X = "<<Test_Vector.X;
cout<<"Member Y = "<<Test_Vector.Y;
cout<<"Member Z = "<<Test_Vector.Z;
float* vector_array = &Test_Vector;
cout<<"Array = {"<<vector_array[0]<<", "<<vector_array[1]<<", "<<vector_array[2]<<"}";
}
Thanks to Operator overloading, we can use the data object as if was an array and we can use it for pass-by-reference in function calls (just like an array)!
If someone with More C++ experience has a better way of applying this end product, I would love to see it!
EDIT: Changed up the code to be more cross-platform friendly
Given your example:
union
{
struct
{
Scalar x, y;
};
Scalar v[2];
};
As others have noted, in general, the standard does not guarantee that there will be no padding between x and y, and actually compilers inserting padding in structures is pretty common behavior.
On the other hand, with solutions like:
struct U
{
int v[2];
int& x;
int& y;
};
U::U()
: x(v[0])
, y(v[1])
{}
what I don't like mainly is the fact that I have to mention x, y twice. For cases where I have more than just a few elements (say 10), this becomes much less readable and harder to maintain - e.g. if you want to change the order of x,y then you have to change the indexes below too (well not mandatory but otherwise order in memory wouldn't match order of fields, which would not be recommended). Also, U can no longer be a POD since it needs a user-defined constructor. And finally, the x & y references consume additional memory.
Hence, the (acceptable for me) compromise I've come up with is:
struct Point
{
enum CoordType
{
X,
Y,
COUNT
};
int coords[CoordType::COUNT];
};
typedef Point::CoordType PtCoord;
With this you can then do:
Point p;
for ( int i = 0; i < PtCoord::COUNT; i++ )
p.coords[i] = 100;
std::cout << p.coords[PtCoord::X] << " " << p.coords[PtCoord::Y] << std::endl;
// 100 100
A bit sophisticated but I prefer this over the references suggestion.
Depending on what "Scalar" is, yes, you can do that in C++. The syntax is almost exactly (maybe even exactly exactly, but I'm rusty on unions) what you wrote in your example. It's the same as C, except there are restrictions on the types that can be in the unions (IIRC they must have a default constructor). Here's the relevant Wikipedia article.
With C++11 you have anonymous unions and structs which just export their definitions to the enclosing scope, so you can do this:
typedef int Scalar;
struct Vector
{
union
{
struct
{
Scalar x, y;
};
Scalar v[2];
};
};