I understand that cl_platform_id is a data structure like:
typedef struct{
foo1 bar1;
foo2 bar2;
...;
}cl_platform_id;
But what are the content of this structure? for example if I want to print these content to the console what data type should I use?
I tried integer but I got the error:
warning: format specifies type 'int' but the argument has type
'cl_platform_id' (aka 'struct _cl_platform_id *') [-Wformat]
Thanks for your help in advance.
The cl_platform_id is an abstract (opaque) type, it is not intended to be directly used. Instead, query the information that you want to know with clGetPlatformInfo on your cl_platform_id. You can get strings (like CL_PLATFORM_NAME) that you can then print.
Thanks to the w-m's answer I was pointed towards the right direction and was to write a snippet to print the platform information:
cl_platform_info Param_Name[5]={CL_PLATFORM_PROFILE, CL_PLATFORM_VERSION, CL_PLATFORM_NAME, CL_PLATFORM_VENDOR, CL_PLATFORM_EXTENSIONS};
cl_platform_info param_name;
size_t param_value_size;
for(int j=0;j<5;j++){
param_name=Param_Name[j];
err = clGetPlatformInfo( platforms[i], param_name, 0, NULL, ¶m_value_size);
char* param_value = (char*)malloc( sizeof(char) * param_value_size);
err = clGetPlatformInfo( platforms[i], param_name, param_value_size, param_value, NULL );
printf("%s\n", param_value);
free(param_value);
}
The complete code can be found here in this GitHub Gist.
Related
I dont understand why initialization of dynamically allocated structure needs to be done like this (using shared ptr)
Just to notify that I am using C++11
If we have struct like this
struct Meme {
std::string s;
Meme* p;
}
and later in code, I need to dynamically allocated memory for this structure using shared_ptr, but I need to do instant initialization of structure.
Why it is done like this?
std::shared_ptr<Meme> novi=std::make_shared<Meme>(Meme{imena.at(i),nullptr});
part that confuses me is this one :
std::make_shared<Meme>(Meme{imena.at(i),nullptr});
If we set that shared_ptr points to struct Meme, why we need to specify again that initialization list is for struct Meme, by saying
(Meme{imena.at(i),nullptr})
Why this would not work:
std::shared_ptr<Meme> novi=std::make_shared<Meme>({imena.at(i),nullptr});
Is this maybe that initialization list cannot deduct that it should like convert to struct Meme because there is no direct usage of struct Meme(even though make_shared points to struct Meme) ?
make_shared forwards arguments to constructor.
Make shared_ptr
Allocates and constructs an object of type T passing args to its constructor, and returns an object of type shared_ptr that owns and stores a pointer to it (with a use count of 1).
This calls the copy constructor of Meme from new instance you create with Meme{imena.at(i),nullptr}.
std::shared_ptr<Meme> novi=std::make_shared<Meme>(Meme{imena.at(i),nullptr});
The correct way to construct it with make_shared from forwarded arguments is to create constructor in struct:
struct Meme {
std::string s;
Meme* p;
Meme(const std::string& s, Meme* p) : s(s), p(p) {}
};
std::shared_ptr<Meme> novi = std::make_shared<Meme>(imena.at(i),nullptr);
Also you can create an instance with (default) empty constructor and then set its members:
struct Meme {
std::string s;
Meme* p = nullptr;
};
std::shared_ptr<Meme> novi = std::make_shared<Meme>;
novi->s = imena.at(i);
The build returns -11 error. Removing pow function compiles fine. I'm not using embedded profile.
__kernel void VectorAdd(__global int* a)
{
unsigned int n = get_global_id(0);
a[n] = pow(2, 2);
}
Im catching the error but the string is empty
int err = clBuildProgram(OpenCLProgram, 0, NULL, NULL, NULL, NULL);
if (err != CL_SUCCESS)
{
size_t len;
char buffer[2048];
printf("Error: Failed to build program executable!\n");
clGetProgramBuildInfo(OpenCLProgram, cdDevice, CL_PROGRAM_BUILD_LOG, sizeof(buffer), buffer, &len);
printf("%s\n", buffer);
exit(1);
}
Some useful info:
CL_DEVICE_NAME: AMD Radeon HD - FirePro D300 Compute Engine
CL_DRIVER_VERSION: 1.2 (Jan 10 2017 22:25:08)
If you look at the OpenCL documentation for pow you will notice that it is defined as gentype pow(gentype x, gentype y). The document also states that
The generic type name gentype is used to indicate that the function can take float, float2, float3, float4, float8, float16, double, double2, double3, double4, double8, or double16 as the type for the arguments.
So pow() takes two float or two double values or vectors thereof and returns a value of the same type. Since the compiler cannot determine wether you wanted to call pow(2.0, 2.0) (double precision) or pow(2.0f, 2.0f) (single precision), you get an error instead.
Note that there is also the similar-named function float pown(float x, int y) which takes an integer value for the exponent (e.g. pown(2.0f, 2)) and may provide an optimized implementation of this case.
What does clGetProgramBuildInfo() with param_name=CL_PROGRAM_BUILD_LOG say? This should give you a much more detailed error message. Update the question with this and I might be able to expand this answer.
What version of OpenCL is this? Note that prior to 1.2, the pow() function was only defined for floating-point types; you're expecting it to work with integers.
I've got the following struct:
struct Param
{
double** K_RP;
};
And I wanna perform the following operations on "K_RP" in CUDA
__global__ void Test( struct Param prop)
{
int ix = threadIdx.x;
int iy = threadIdx.y;
prop.K_RP[ix][iy]=2.0;
}
If "prop" has the following form, how should I do my "cudaMalloc" and "cudaMemcpy" operations?
int main( )
{
Param prop;
Param cuda_prop;
prop.K_RP=alloc2D(Imax,Jmax);
//cudaMalloc cuda_prop ?
//cudaMemcpyH2D prop to cuda_prop ?
Test<<< (1,1), (Imax,Jmax)>>> ( cuda_prop);
//cudaMemcpyD2H cuda_prop to prop ?
return (0);
}
Questions like this get asked from time to time. If you search on the cuda tag, you'll find a variety of examples with answers. Here's one example.
In general, dynamically allocated data contained within structures or other objects requires special handling. This question/answer explains why and how to do it for the single pointer (*) case.
Handling double pointers (**) is difficult enough that most people would recommend "flattening" the storage so that it can be handled by reference with a single pointer (*). If you really want to see how the double pointer (**) method works, review this question/answer. It's not trivial.
I'm brand new to using OpenCL, and this seems like it should be very simple, so bear with me.
I'm writing a simple kernel to scan an array and look for a particular value. If that value is found anywhere in the array, I'd like a flag to be set. If the value is not found, the flag should remain 0;
Currently I'm creating a cl_mem object to hold an int
cl_mem outputFlag = clCreateBuffer(mCLContext, CL_MEM_WRITE_ONLY, sizeof(cl_int), NULL, NULL);
setting it as a kernel argument
clSetKernelArg(mCLKernels[1],1, sizeof(cl_mem), &outputFlag);
and executing my kernel which looks like:
__kernel void checkForHole(__global uchar *image , __global int found, uchar holeValue)
{
int i = get_global_id(0);
int j = get_global_id(1);
uchar sample = image[i*j];
if (sample == holeValue) {
found = 1;
}
}
Note that my array is 2D, though it shouldn't matter.
When I put a printf statement inside my found condition, it does get called (the value is found). But when I read back my value via:
cl_int result;
errorCode = clEnqueueReadBuffer(mCLCommandQueue, outputFlag, CL_TRUE
, 0, sizeof(cl_int), &result, 0, NULL, NULL);
I get 0. Is there a proper way to set a flag in openCL? it would also be nice if there was a way to halt the entire execution and just return my value if it is found.
Can I write a bool return type kernel and just return true?
Thanks!
In the kernel the output flag should be a pointer to an int.
Change the kernel parameter to __global int *found
I always seem to figure out my issues just by writing them here....
If anyone knows a way to halt the execution though, or if it's even possible, I'd still be interested :)
I'm working on the development of a C++ API which uses custom-designed plugins
to interface with different database engines using their APIs and specific SQL
syntax.
Currently, I'm attempting to find a way of inserting BLOBs, but since NULL is
the terminating character in C/C++, the BLOB becomes truncated when constructing
the INSERT INTO query string. So far, I've worked with
//...
char* sql;
void* blob;
int len;
//...
blob = some_blob_already_in_memory;
len = length_of_blob_already_known;
sql = sqlite3_malloc(2*len+1);
sql = sqlite3_mprintf("INSERT INTO table VALUES (%Q)", (char*)blob);
//...
I expect that, if it is at all possible to do it in the SQLite3 interactive console, it should be possible to construct the query string with properly escaped NULL characters. Maybe there's a way to do this with standard SQL which is also supported by SQLite SQL syntax?
Surely someone must have faced the same situation before. I've googled and found some answers but were in other programming languages (Python).
Thank you in advance for your feedback.
Thank you all again for your feedback. This time I'm reporting how I solved the problem with the help of the indications provided here. Hopefully this will help others in the future.
As suggested by the first three posters, I did use prepared statements — additionally because I was also interested in getting the columns' data types, and a simple sqlite3_get_table() wouldn't do.
After preparing the SQL statement in the form of the following constant string:
INSERT INTO table VALUES(?,?,?,?);
it remains the binding of the corresponding values. This is done by issuing as many sqlite3_bind_blob() calls as the columns. (I also resorted to sqlite3_bind_text() for other "simple" data types because the API I'm working on can translate integers/doubles/etc into a string). So:
#include <stdio.h>
#include <string.h>
#include <sqlite3.h>
/* ... */
void* blobvalue[4] = { NULL, NULL, NULL, NULL };
int blobsize[4] = { 0, 0, 0, 0 };
const char* tail = NULL;
const char* sql = "INSERT INTO tabl VALUES(?,?,?,?)";
sqlite3_stmt* stmt = NULL;
sqlite3* db = NULL;
/* ... */
sqlite3_open("sqlite.db", &db);
sqlite3_prepare_v2(db,
sql, strlen(sql) + 1,
&stmt, &tail);
for(unsigned int i = 0; i < 4; i++) {
sqlite3_bind_blob(stmt,
i + 1, blobvalue[i], blobsize[i],
SQLITE_TRANSIENT);
}
if(sqlite3_step(stmt) != SQLITE_DONE) {
printf("Error message: %s\n", sqlite3_errmsg(db));
}
sqlite3_finalize(stmt);
sqlite3_close(db);
Note also that some functions (sqlite3_open_v2(), sqlite3_prepare_v2()) appear on the later SQLite versions (I suppose 3.5.x and later).
The SQLite table tabl in file sqlite.db can be created with (for example)
CREATE TABLE tabl(a TEXT PRIMARY KEY, b TEXT, c TEXT, d TEXT);
You'll want to use this function with a prepared statement.
int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*));
In C/C++, the standard way of dealing with NULLs in strings is to either store the beginning of the string and a length, or store a pointer to the beginning of a string and one to the end of the string.
You want to precompile the statement sqlite_prepare_v2(), and then bind the blob in using sqlite3_bind_blob(). Note that the statement you bind in will be INSERT INTO table VALUES (?).