I'm implementing a small template app for openCL applications, and more specifically I'm creating a context right now.
I was reading through the documentation https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clCreateContext.html
And I quote:
Specifies a list of context property names and their corresponding values. Each property name is immediately followed by the corresponding desired value. The list is terminated with 0. properties can be NULL in which case the platform that is selected is implementation-defined. The list of supported properties is described in the table below.
And then there's the list...
I cannot figure however what is the purpose of these properties, how exactly are they used for? How does specifying these properties affect my program execution or just the design? I've seen few examples where this argument is just set to 0 or nullptr.
Can you clarify?
The CL_CONTEXT_PLATFORM property allows you to select a particular platform ID. For clCreateContext() this isn't terribly useful as the platform will be implicitly selected via the device list anyway. However, for clCreateContextFromType() this lets you create a context for e.g. "all the GPUs in the system using the AMD implementation" (as opposed to the Intel implementation).
The other properties facilitate interoperation between OpenCL and other graphics or compute libraries such as OpenGL, DirectX, and such. So if you want to share textures between OpenCL and OpenGL, this tells your OpenCL implementation for which OpenGL context you will be providing texture names, which are just integer handles and non-unique across OpenGL contexts.
From a practical point of view, you pass the properties as a 0-terminated array, e.g.:
cl_context_properties properties[] =
{
CL_CONTEXT_PLATFORM, selected_platform_id,
0 // signals end of property list
};
cl_int error = 0;
cl_context context = clCreateContextFromType(properties, CL_DEVICE_TYPE_GPU, NULL, NULL, &error);
Related
clBuildProgram allows one to give a list of devices to build the program for. That's the reason of the num_devices and device_list parameters in the declaration:
cl_int clBuildProgram(cl_program program, cl_uint num_devices, const cl_device_id *device_list, const char *options, void (CL_CALLBACK *pfn_notify)(cl_program program, void *user_data), void *user_data)
Now what happens, if we use it like this?
cl_int clBuildProgram(program, 0, NULL, ...
Does it build for all devices in the PC?
Does it build for only those devices I have created the context for? (I mean the context I used when I created program with clCreateProgramWithSource.)
The documentation says:
device_list: A pointer to a list of devices associated with program. If device_list is NULL value, the program executable is built for all devices associated with program for which a source or binary has been loaded. If device_list is a non-NULL value, the program executable is built for devices specified in this list for which a source or binary has been loaded.
I think the phrasing is a bit complicated here, but from that, I guess number 2. Is that right?
I am asking because in case of number 1, I would need to pass a device list to this function in order to avoid superfluous compilation for all devices.
2) is correct. Compilation is constrained to only the devices associated with the program's context. This cannot be every single device in the system unless the context was created using every single device.
Reading Qt signal & slots documentation, it seems that the only reason for a new style connection to fail is:
"If there is already a duplicate (exact same signal to the exact same slot on the same objects), the connection will fail and connect will return false"
Which means that connection was already successful the first time and does not allow multi-connections when using Qt::UniqueConnection.
Does this means that Qt-5 style connection will always success? Are there any other reasons for failure?
The new-style connect can still fail at runtime for a variety of reasons:
Either sender or receiver is a null pointer. Obviously this requires a check that can only happen at runtime.
The PMF you specified for a signal is not actually a signal. Lacking proper C++ reflection capabilities, all you can do at compile time is checking that the signal is a non-static member function of the sender's class.
However, that's not enough to make it a signal: it also needs to be in a signals: section in your class definition. When moc sees your class definition, it will generate some metadata containing the information that that function is indeed a signal. So, at runtime, the pointer passed to connect is looked up in a table, and connect itself will fail if the pointer is not found (because you did not pass a signal).
The check on the previous point actually requires a comparison between pointers to member functions. It's a particularly tricky one, because it will typically involve different TUs:
one is the TU containing moc-generated data (typically a moc_class.cpp file). In this TU there's the aforementioned table containing, amongst other things, pointers to the signals (which are just ordinary member functions).
is the TU where you actually invoke connect(sender, &Sender::signal, ...), which generates the pointer that gets looked up in the table.
Now, the two TUs may be in the same application, or perhaps one is in a library and the other in your application, or maybe in two libraries, etc; your platform's ABI starts to get into play.
In theory, the pointers stored when doing 1. are identical to the pointers generated when doing 2.; in practice, we've found cases where this does not happen (cf. this bug report that I reported some time ago, where older versions of GNU ld on ARM generated code that failed the comparison).
For Qt this meant disabling certain optimizations and/or passing some extra flags to the places where we know this to happen and break user software. For instance, as of Qt 5.9, there is no support for -Bsymbolic* flags on GCC on anything but x86 and x86-64.
Of course, this does not mean we've found and fixed all the possible places. New compilers and more aggressive optimizations might trigger this bug again in the future, making connect return false, even when everything is supposed to work.
Yes it can fail if either sender or receiver are not valid objects (nullptr for example)
Example
QObject* obj1 = new QObject();
QObject* obj2 = new QObject();
// Will succeed
connect(obj1, &QObject::destroyed, obj2, &QObject::deleteLater);
delete obj1;
obj1 = nullptr;
// Will fail even if it compiles
connect(obj1, &QObject::destroyed, obj2, &QObject::deleteLater);
Do not try to register pointer type. I've used the macro
#define QT_REG_TYPE(T) qRegisterMetaType<T>(#T)
with pointer type CMyWidget*, that was the problem. Using the type directly worked.
No it's not always successful. The docs give an example here where connect would return false because the signal should not contain variable names.
// WRONG
QObject::connect(scrollBar, SIGNAL(valueChanged(int value)),
label, SLOT(setNum(int value)));
The last attribute of glVertexAttribPointer is of type const GLvoid*. But is it really a pointer? It is actually an offset. If I put 0, it means an offset of 0 and not a null pointer to an offset. In my engine, I use this function:
void AbstractVertexData::vertexAttribPtr(int layout) const
{
glVertexAttribPointer(layout,
getShaderAttribs()[layout]->nbComponents,
static_cast<GLenum>(getShaderAttribs()[layout]->attribDataType),
getShaderAttribs()[layout]->shouldNormalize,
getVertexStride(layout),
reinterpret_cast<const void*>(getVertexAttribStart(layout)));
}
getVertexAttribStart returns an intptr_t. When I run drmemory, it says "uninitialized read" and I want to remove that warning. This warning comes from the reinterpret_cast. I can't static_cast to a const void* since my value isn't a pointer. What should I do to fix this warning?
Originally, back in OpenGL-1.1 when vertex arrays got introduces, functions like glVertexPointer, glTexCoordPointer and so on were accepting pointers into client address space. When shaders got introduced they came with arbitrary vertex attributes and the function glVertexAttribPointer follows the same semantics (this was in OpenGL-2.1).
The buffer objects API was then reusing existing functions, where you'd pass an integer for a pointer parameter.
OpenGL-3.3 core eventually made the use of buffer objects mandatory and ever since the glVertexAttribPointer functions being defines with a void* in their function signature are a sore spot; I've written in extent about it in https://stackoverflow.com/a/8284829/524368 (but make sure to read the rest of the answers as well).
Eventually new functions got introduced that allow for a more fine grained control over how vertex attributes are accessed, replacing glVertexAttribPointer, and those operate purely on offsets.
I'm new to OpenCL, and have followed this tutorial to get started. Before creating the cl::Context, the tutorial creates a static array of three cl_context_properties which it doesn't explain what it is for, but which it sends as the properties argument in the cl::Context constructor.
However when looking at the reference page for cl::Context, there is no explanation of what the properties parameter is, but it does say that it "is reserved and must be zero". So why does the tutorial send a non-zero value as that argument? What purpose does it serve? And if you have been able to pass that argument before, how does it come that it is suddenly "reserved", doesn't that make OpenCL non-backward compatible?
The code compiles and runs fine both with and without the parameter there. The only difference is that I get a warning that cprops is unused when putting NULL there instead of cprops.
Also, when I pass CL_DEVICE_TYPE_CPU | CL_DEVICE_TYPE_GPU as the type argument to the cl::Context constructor, my application will crash (SIGSEGV) when I later try to create a cl::Buffer with the context. Why? Am I not able to specify more than one device type to use simultaneously?
Update: By giving NULL as the properties argument to the cl::Context constructor, the variable platformList is suddenly not used to anything OpenCL related anymore. The tutorial seems to use platformList to specify the platform for which the cl::Context should be created, but now the context is just created like this:
cl::Context context(
CL_DEVICE_TYPE_GPU,
NULL,
NULL,
NULL,
&err);
so I don't get to specify the platform. Shouldn't I get to do that? How does it come I can't do that when the tutorial seemed to be doing that?
On your first question, see the official OpenCL documentation for a description of this parameter: http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/. This is the C API, but it is the same as the C++ API.
As to your second question - you may want to check the error result from creating the context to see why it doesn't like the type parameters you specify.
How can one create a dictionary of objects with weak references -- that is, the dictionary does not retain its keys and values -- on OS X 10.7 with ARC enabled? NSMapTable looks promising but unfortunately it doesn't use weak references when ARC is enabled.
NSMapTable is indeed what you want.
10.8+:
specifically in your case it sounds like you want to use this:
+ (id)weakToWeakObjectsMapTable
Return Value
A new map table object which has weak references to the keys and values.
from the docs:
The major option is to have keys and/or values held “weakly” in a manner that entries are removed when one of the objects is reclaimed.
you can use either the shortcut class methods + (id)weakToWeakObjectsMapTable or + (id)weakToStrongObjectsMapTable depending on your needs.
also see NSMapTableOptions to see how to specify behavior to the other initializers.
NSMapTableWeakMemory
Uses weak read and write barriers appropriate for ARC or GC. Using NSPointerFunctionsWeakMemory object references will turn to NULL on last release. Equal to NSMapTableZeroingWeakMemory.
10.7+:
use – initWithKeyOptions:valueOptions:capacity: and pass NSMapTableZeroingWeakMemory in the options (assuming your objects are "weak-reference-safe")
alternatively you can use – initWithKeyPointerFunctions:valuePointerFunctions:capacity: and specify custom functions if none of the built in ones work for you / arent available on you version. (maybe one of the "opaque" personalities would work for you)