OpenCL cannot find GPU device: NVIDIA GPU (Quadro K4000) + Visual Studio 2015 - opencl

Just started to learn OpenCL and setup a Visual Studio project using VS2015. Somehow, the code can find only 1 platform (I guess it should be the CPU), and cannot find the GPU device. Can someone please help? The detailed information is as follows:
GPU: Nvidia Quadro K4000
CUDA Installation
CUDA is at: “C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v7.5”
OpenCL related files are located at "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v7.5\include\CL" and "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v7.5\lib\Win32" (assuming 32bit system)
The installer created two environment variables “CUDA_PATH” and “CUDA_PATH_V7_5”. They both point to the above location.
In Visual Studio, the project is set up as
"Project Properties" -> "C/C++" -> "Additional Include Directories" -> "$(CUDA_PATH)\include"
"Project Properties" -> "Linker" -> "Additional Library Directories" -> "$(CUDA_PATH)\lib\Win32"
"Project Properties" -> "Linker" -> "Input" -> "Additional Dependencies" -> "OpenCL.lib"
The code is very simple:
#include "stdafx.h"
#include <iostream>
#include <CL/cl.h>
using namespace std;
int main()
{
cl_int err;
cl_uint numPlatforms;
err = clGetPlatformIDs(0, NULL, &numPlatforms);
if (CL_SUCCESS == err)
cout << "Detected OpenCL platforms: " << numPlatforms << endl;
else
cout << "Error calling clGetPlatformIDs. Error code:" << err << endl;
cl_device_id device = NULL;
err = clGetDeviceIDs(NULL, CL_DEVICE_TYPE_GPU, 1, &device, NULL);
if (err == CL_SUCCESS)
cout << device << endl;
return 0;
}
The code compiles and runs, but it cannot the GPU device. Specifically, the returned value of variable device is device = 0x00000000 <NULL>. What would be the problem? Thanks for the help.

This is not the way you use the OpenCL API.
You need to obtain a valid cl_platform_id object which it needs to be used to retrieve a cl_device_id. You are always passing NULL, this can't work.
The first time you invoke the clGetPlatformIds, you do it in order to obtain the number of platforms in the system. After than you need to invoke the method again in order to retrieve the actual cl_platform_ids:
size_t numPlatforms;
err = clGetPlatformIDs(0, NULL, &numPlatforms);
assert(numPlatforms > 0);
cl_platform_id platform_ids[numPlatforms];
err = clGetPlatformIDs(numPlatforms, platform_ids, NULL);
However, if you already know there is going to be only one platform in the system, then you can do speedup things as follows, but make sure to check for errors:
cl_platform_id platform_id;
err = clGetPlatformIDs(1, &platform_id, NULL);
assert(err == CL_SUCCESS);
After you have obtained a platform you need to follow the same procedure to first obtain the number of devices and then retrieve the list of OpenCL devices (which you then will need to build a cl_context, queues...):
// Note: this has to be done for each `cl_platform_id`
// until you find the device you were looking for
size_t numDevices;
err = clGetDeviceIDs(platform_id, CL_DEVICE_TYPE_GPU, 0, NULL, &numDevices);
assert(numDevices > 0);
cl_device_id devices[numDevices];
err = clGetDeviceIDs(platform_id, CL_DEVICE_TYPE_GPU, numDevices, devices, NULL);
I guess you understand the procedure now. If like above, you already know that there is only 1 GPU device in the system, you can directly get its cl_device_id as follows:
cl_device_id device;
err = clGetDeviceIDs(platform_id, CL_DEVICE_TYPE_GPU, 1, &device, NULL);
assert(err == CL_SUCCESS);

Related

Can I link two separate executables with MPI_open_port and share port information in a text file?

I'm trying to create a shared MPI COMM between two executables which are both started independently, e.g.
mpiexec -n 1 ./exe1
mpiexec -n 1 ./exe2
I use MPI_Open_port to generate port details and write these to a file in exe1 and then read with exe2. This is followed by MPI_Comm_connect/MPI_Comm_accept and then send/recv communication (minimal example below).
My question is: can we write port information to file in this way, or is the MPI_Publish_name/MPI_Lookup_name required for MPI to work as in this, this and this? As supercomputers usually share a file system, this file based approach seems simpler and maybe avoids establishing a server.
It seems this should work according to the MPI_Open_Port documentation in the MPI 3.1 standard,
port_name is essentially a network address. It is unique within the communication universe to which it belongs (determined by the implementation), and may be used by any client within that communication universe. For instance, if it is an internet (host:port) address, it will be unique on the internet. If it is a low level switch address on an IBM SP, it will be unique to that SP
In addition, according to documentation on the MPI forum:
The following should be compatible with MPI: The server prints out an address to the terminal, the user gives this address to the client program.
MPI does not require a nameserver
A port_name is a system-supplied string that encodes a low-level network address at which a server can be contacted.
By itself, the port_name mechanism is completely portable ...
Writing the port information to file does work as expected, i.e creates a shared communicator and exchanges information using MPICH (3.2) but hangs at the MPI_Comm_connect/MPI_Comm_accept line when using OpenMPI versions 2.0.1 and 4.0.1 (on my local workstation running Ubuntu 12.04 but eventually needs to work on a tier 1 supercomputer). I have raised as an issue here but welcome a solution or workaround in the meantime.
Further Information
If I use the MPMD mode with OpenMPI,
mpiexec -n 1 ./exe1 : -n 1 ./exe2
this works correctly, so must be an issue with allowing the jobs to share ompi_global_scope as in this question. I've also tried adding,
MPI_Info info;
MPI_Info_create(&info);
MPI_Info_set(info, "ompi_global_scope", "true");
with info passed to all commands, with no success. I'm not running a server/client model as both codes run simultaneously so sharing a URL/PID from one is not ideal, although I cannot get this to work even using the suggested approach, which for OpenMPI 2.0.1,
mpirun -n 1 --report-pid + ./OpenMPI_2.0.1 0
1234
mpirun -n 1 --ompi-server pid:1234 ./OpenMPI_2.0.1 1
gives,
ORTE_ERROR_LOG: Bad parameter in file base/rml_base_contact.c at line 161
This failure appears to be an internal failure;
here's some additional information (which may only be relevant to an
Open MPI developer):
pmix server init failed
--> Returned value Bad parameter (-5) instead of ORTE_SUCCESS
and with OpenMPI 4.0.1,
mpirun -n 1 --report-pid + ./OpenMPI_4.0.1 0
1234
mpirun -n 1 --ompi-server pid:1234 ./OpenMPI_4.0.1 1
gives,
ORTE_ERROR_LOG: Bad parameter in file base/rml_base_contact.c at line 50
...
A publish/lookup server was provided, but we were unable to connect
to it - please check the connection info and ensure the server
is alive:
Using 4.0.1 means the error should not be related to this bug in OpenMPI.
Minimal code
#include "mpi.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <iostream>
#include <fstream>
using namespace std;
int main( int argc, char *argv[] )
{
int num_errors = 0;
int rank, size;
char port1[MPI_MAX_PORT_NAME];
char port2[MPI_MAX_PORT_NAME];
MPI_Status status;
MPI_Comm comm1, comm2;
int data = 0;
char *ptr;
int runno = strtol(argv[1], &ptr, 10);
for (int i = 0; i < argc; ++i)
printf("inputs %d %d %s \n", i,runno, argv[i]);
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &size);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
if (runno == 0)
{
printf("0: opening ports.\n");fflush(stdout);
MPI_Open_port(MPI_INFO_NULL, port1);
printf("opened port1: <%s>\n", port1);
//Write port file
ofstream myfile;
myfile.open("port");
if( !myfile )
cout << "Opening file failed" << endl;
myfile << port1 << endl;
if( !myfile )
cout << "Write failed" << endl;
myfile.close();
printf("Port %s written to file \n", port1); fflush(stdout);
printf("Attempt to accept port1.\n");fflush(stdout);
//Establish connection and send data
MPI_Comm_accept(port1, MPI_INFO_NULL, 0, MPI_COMM_WORLD, &comm1);
printf("sending 5 \n");fflush(stdout);
data = 5;
MPI_Send(&data, 1, MPI_INT, 0, 0, comm1);
MPI_Close_port(port1);
}
else if (runno == 1)
{
//Read port file
size_t chars_read = 0;
ifstream myfile;
//Wait until file exists and is avaialble
myfile.open("port");
while(!myfile){
myfile.open("port");
cout << "Opening file failed" << myfile << endl;
usleep(30000);
}
while( myfile && chars_read < 255 ) {
myfile >> port1[ chars_read ];
if( myfile )
++chars_read;
if( port1[ chars_read - 1 ] == '\n' )
break;
}
printf("Reading port %s from file \n", port1); fflush(stdout);
remove( "port" );
//Establish connection and recieve data
MPI_Comm_connect(port1, MPI_INFO_NULL, 0, MPI_COMM_WORLD, &comm1);
MPI_Recv(&data, 1, MPI_INT, 0, 0, comm1, &status);
printf("Received %d 1\n", data); fflush(stdout);
}
//Barrier on intercomm before disconnecting
MPI_Barrier(comm1);
MPI_Comm_disconnect(&comm1);
MPI_Finalize();
return 0;
}
The 0 and 1 simply specify if this code writes a port file or reads it in the example above. This is then run with,
mpiexec -n 1 ./a.out 0
mpiexec -n 1 ./a.out 1

clGetPlatformID error when running OpenCL program.

I've been trying to make OpenCL work in my laptop. I followed this link for that. I have an NVIDIA GT525M video card and Windows 8.1.
The steps I followed were:
Installing the up-to-date NVIDIA drivers.
Installing Visual Studio 2013 Community Edition.
Adding the paths for the linker and the compiler.
and then I tried to run the following code as given in that page:
#include <stdio.h>
#include <CL/cl.h>
int main(void)
{
cl_int err;
cl_uint* numPlatforms=NULL;
err = clGetPlatformIDs(0, NULL,numPlatforms);
if (CL_SUCCESS == err)
printf("\nDetected OpenCL platforms: %d", numPlatforms);
else
printf("\nError calling clGetPlatformIDs. Error code: %d", err);
getchar();
return 0;
}
The code builds successfully but the result I get is:
Error calling clGetPlatformIDs. Error code: -30
I get zero as the number of platforms.
I've been looking all over the internet for a solution but couldn't find one. Please help.
This:
cl_uint* numPlatforms=NULL;
err = clGetPlatformIDs(0, NULL,numPlatforms);
Is equivalent to this:
err = clGetPlatformIDs(0, NULL, NULL);
Which doesn't make sense. As per the documentation:
Returns CL_SUCCESS if the function is executed successfully. Otherwise it returns CL_INVALID_VALUE if num_entries is equal to zero and platforms is not NULL, or if both num_platforms and platforms are NULL.
CL_INVALID_VALUE is the -30 you are getting, for the reasons stated above.
What you really want is the following:
cl_uint numPlatforms = 0;
err = clGetPlatformIDs(0, NULL, &numPlatforms);

How to check why QOpenGLVertexArrayObject::create fails

I have got the following code for creating a VAO :
// VAO
mVAO = new QOpenGLVertexArrayObject();
if (!mVAO->create()) {
qDebug() << "ERROR: VAO creation failed";
}
mVAO->bind();
// VBO
mVBO = new QOpenGLBuffer(QOpenGLBuffer::VertexBuffer);
if (!mVBO->create()) {
qDebug() << "ERROR: VBO creation failed";
}
mVBO->setUsagePattern( QOpenGLBuffer::StreamDraw );
mVBO->bind();
mVBO->allocate( mVertices.constData(), mVertices.count() * 3 * sizeof( float ) );
mProgram.enableAttributeArray(mVertexAttrLoc);
mProgram.setAttributeBuffer(mVertexAttrLoc, GL_FLOAT, 0, 3 ); // uses the currently bound VBO
// This is imp, we do not want any more state info recorded
mVAO->release();
mVAO->create() fails in the above code. But the VBO creation does not fail. I am not sure how to find out a more detailed reason as to why the VAO creation fails.
One other thing is I am using Qt 5.2 and a laptop with a dual video card and the nvidia optimus thingy. But I can see the program is executed by the nvidia card and not the onboard intel card. So it probably is not a hardware capabilities issue.
The OpenGL version reported by
qDebug() << "OpenGL version:" << QGLFormat::openGLVersionFlags();
is OpenGL version: QFlags(0x800) which is QGLFormat::OpenGL_ES_Version_2_0
Maybe the ES version is whats standard in laptops ?
I used this as a reference to write the code : http://www.kdab.com/opengl-in-qt-5-1-part-2/

Qt 4.7.4: Is there a way to find out the status of CAPS LOCK?

I know there were earlier problems with this in < 4.7.4 Qt versions. has this been resolved?
I don't know any Qt solution.
However this code should work on both windows (not tested) and x11-based os (works on linux)
#include <X11/XKBlib.h>
#include <QX11Info>
bool capsOn()
{
#ifdef Q_WS_WIN // MS Windows version
return GetKeyState(VK_CAPITAL) == 1;
#elif Q_WS_X11 // X11 version
unsigned int n = 0;
Display *d = QX11Info::display();
XkbGetIndicatorState(d, XkbUseCoreKbd, &n);
return (n & 0x01) == 1;
#else
# error Platform not supported
#endif
}
On X11 don't forget to add -lX11 to LIBS in your qmake project file.
I don't exactly know how to do this on OS X. If you need it, take a look at IOHIKeyboard and its's alphaLock() function. Also check this, especially the function darwinQueryHIDModifiers.

clBuildProgram failed with error code -11 and without build log

I have worked little bit in OpenCL now but recently "clBuildProgram" failed in one of my program. My code excerpt is below:
cl_program program;
program = clCreateProgramWithSource(context, 1, (const char**) &kernel_string, NULL, &err);
if(err != CL_SUCCESS)
{
cout<<"Unable to create Program Object. Error code = "<<err<<endl;
exit(1);
}
if(clBuildProgram(program, 0, NULL, NULL, NULL, NULL) != CL_SUCCESS)
{
cout<<"Program Build failed\n";
size_t length;
char buffer[2048];
clGetProgramBuildInfo(program, device_id[0], CL_PROGRAM_BUILD_LOG, sizeof(buffer), buffer, &length);
cout<<"--- Build log ---\n "<<buffer<<endl;
exit(1);
}
Normally earlier I got syntax or other errors inside kernel file here with the help of "clGetProgramBuildInfo()" function whenever "clBuildProgram" Failed but when this program runs, on console it only prints:
Program Build failed
--- Build log ---
And when I tried to print the error code returned by "clBuildProgram"; it is "-11"......
What can be the problem with my kernel file that I dont get any build fail information ?
You can learn the meaning of OpenCL error codes by searching in cl.h. In this case, -11 is just what you'd expect, CL_BUILD_PROGRAM_FAILURE. It's certainly curious that the build log is empty. Two questions:
1.) What is the return value from clGetProgramBuildInfo?
2.) What platform are you on? If you are using Apple's OpenCL implementation, you could try setting CL_LOG_ERRORS=stdout in your environment. For example, from Terminal:
$ CL_LOG_ERRORS=stdout ./myprog
It's also pretty easy to set this in Xcode (Edit Scheme -> Arguments -> Environment Variables).
If you are using the C instead of C++:
err = clBuildProgram(program, 0, NULL, NULL, NULL, NULL);
////////////////Add the following lines to see the log file///////////
if (err != CL_SUCCESS) {
char *buff_erro;
cl_int errcode;
size_t build_log_len;
errcode = clGetProgramBuildInfo(program, devices[0], CL_PROGRAM_BUILD_LOG, 0, NULL, &build_log_len);
if (errcode) {
printf("clGetProgramBuildInfo failed at line %d\n", __LINE__);
exit(-1);
}
buff_erro = malloc(build_log_len);
if (!buff_erro) {
printf("malloc failed at line %d\n", __LINE__);
exit(-2);
}
errcode = clGetProgramBuildInfo(program, devices[0], CL_PROGRAM_BUILD_LOG, build_log_len, buff_erro, NULL);
if (errcode) {
printf("clGetProgramBuildInfo failed at line %d\n", __LINE__);
exit(-3);
}
fprintf(stderr,"Build log: \n%s\n", buff_erro); //Be careful with the fprint
free(buff_erro);
fprintf(stderr,"clBuildProgram failed\n");
exit(EXIT_FAILURE);
}
I encountered the same problem with an empty log file. I was testing my ocl kernel on a different computer. It had 2 platforms instead of one. One Intel GPU and one AMD GPU. I only had AMD OCL SDK installed. Installing the Intel OCL SDK fixed the problem. Also selecting the AMD platform instead of the Intel GPU platform fixed it.
I've seen this happen on OSX 10.14.6 when the OpenCL kernel source is missing the _kernel attribute tag. If both the _kernel tag and return type are missing it seems to crash the system OpenCL compiler daemon, which then takes a few seconds to restart before new kernels will compile again.

Resources