OpenCL error Class gives error in C++ host - c++

I am trying to catch an error in a C++ OpenCL host and it does not compile. This is the program:
#include "gpu/cldrive/libcldrive.h"
#include "gpu/cldrive/kernel_arg_value.h"
#include "gpu/cldrive/kernel_driver.h"
#include "gpu/clinfo/libclinfo.h"
#include "labm8/cpp/logging.h"
#include "labm8/cpp/status.h"
#include "labm8/cpp/statusor.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_format.h"
#include "absl/strings/strip.h"
#include "absl/time/clock.h"
#include "absl/time/time.h"
#define CL_HPP_ENABLE_EXCEPTIONS
#define LOG_CL_ERROR(level, error) \
LOG(level) << "OpenCL exception: " << error.what() << ", error: " \
<< labm8::gpu::clinfo::OpenClErrorString(error.err());
namespace gpu {
namespace cldrive {
namespace {
// Attempt to build OpenCL program.
labm8::StatusOr<cl::Program> BuildOpenClProgram(
const std::string& opencl_kernel, const cl::Context& context,
const string& cl_build_opts) {
auto start_time = absl::Now();
try {
// Assemble the build options. We need -cl-kernel-arg-info so that we can
// read the kernel signatures.
string all_build_opts = "-cl-kernel-arg-info ";
absl::StrAppend(&all_build_opts, cl_build_opts);
labm8::TrimRight(all_build_opts);
cl::Program program;
// SPIR-V Compilation
if(opencl_kernel.substr( opencl_kernel.length() - 4 ) == ".spv") {
std::vector<char> cl_kernel(opencl_kernel.begin(), opencl_kernel.end());
program = cl::Program{context, cl_kernel};
// OPENCL:
} else {
program = cl::Program{context, opencl_kernel};
}
program.build(context.getInfo<CL_CONTEXT_DEVICES>(),
all_build_opts.c_str());
auto end_time = absl::Now();
auto duration = (end_time - start_time) / absl::Milliseconds(1);
LOG(INFO) << "clBuildProgram() with options '" << all_build_opts
<< "' completed in " << duration << " ms";
return program;
} catch (cl::Error e) {
LOG_CL_ERROR(WARNING, e);
return labm8::Status(labm8::error::Code::INVALID_ARGUMENT,
"clBuildProgram failed");
}
}
} // namespace
When building with bazel, it gives me the following error:
ERROR: /home/enrique/Escritorio/cldrive/gpu/cldrive/BUILD:315:1: Couldn't
build file gpu/cldrive/_objs/libcldrive/libcldrive.pic.o: C++
compilation of rule '//gpu/cldrive:libcldrive' failed (Exit 1) gcc
failed: error executing command /usr/bin/gcc -U_FORTIFY_SOURCE
-fstack-protector -Wall -Wunused-but-set-parameter -Wno-free-nonheap-object -fno-omit-frame-pointer -g0 -O2 '-D_FORTIFY_SOURCE=1' -DNDEBUG -ffunction-sections ... (remaining 299
argument(s) skipped)
Use --sandbox_debug to see verbose messages from the sandbox In file
included from ./gpu/cldrive/libcldrive.h:21:0,
from gpu/cldrive/libcldrive.cc:16: ./third_party/opencl/cl.hpp:438:109: note: #pragma message: cl2.hpp:
CL_HPP_TARGET_OPENCL_VERSION is not defined. It will default to 220
(OpenCL 2.2) # pragma message("cl2.hpp: CL_HPP_TARGET_OPENCL_VERSION
is not defined. It will default to 220 (OpenCL 2.2)")
^ gpu/cldrive/libcldrive.cc: In function 'labm8::StatusOr<cl::Program>
gpu::cldrive::{anonymous}::BuildOpenClProgram(const string&, const
cl::Context&, const string&)': gpu/cldrive/libcldrive.cc:76:16: error:
'Error' in namespace 'cl' does not name a type } catch (cl::Error
e) {
^~~~~ gpu/cldrive/libcldrive.cc:77:27: error: 'e' was not declared in this scope
LOG_CL_ERROR(WARNING, e);
^ gpu/cldrive/libcldrive.cc:34:41: note: in definition of macro 'LOG_CL_ERROR' LOG(level) << "OpenCL exception:
" << error.what() << ", error: " \
^~~~~ gpu/cldrive/libcldrive.cc: In member function 'void
gpu::cldrive::Cldrive::RunOrDie(gpu::cldrive::Logger&)':
gpu/cldrive/libcldrive.cc:93:16: error: 'Error' in namespace 'cl' does
not name a type } catch (cl::Error error) {
^~~~~ gpu/cldrive/libcldrive.cc:95:41: error: 'error' was not declared in this scope
<< " Raised by: " << error.what() << '\n'
^~~~~ gpu/cldrive/libcldrive.cc:95:41: note: suggested alternative: In file
included from ./gpu/cldrive/logger.h:21:0,
from ./gpu/cldrive/libcldrive.h:18,
from gpu/cldrive/libcldrive.cc:16: ./labm8/cpp/status.h:41:11: note: 'labm8::error' namespace error {
^~~~~
In the class header (libcldrive.h) the header cl2.hpp is included. This code worked with old headers, it began giving error when updating the old cl.hpp to cl2.hpp. I look for the class in the new header and it still exists, so i do not understand why it is giving error.
Thanks in advance.

Hans has already linked to another question about the same issue in the comments, but although correct, I don't find the answer there particularly complete, helpful, or friendly.
Essentially, raising exceptions on OpenCL errors is an optional feature of the C++ wrapper. (exceptions in C++ are controversial to say the least) So it needs to be explicitly enabled using the CL_HPP_ENABLE_EXCEPTIONS preprocessor macro, before #includeing the wrapper header.
This is documented in the C++ wrapper's documentation here.
The documentation also gives a helpful example, where this feature is enabled:
#define CL_HPP_ENABLE_EXCEPTIONS
#define CL_HPP_TARGET_OPENCL_VERSION 200
#include <CL/cl2.hpp>
Note that your build is also warning you about not defining CL_HPP_TARGET_OPENCL_VERSION - you probably should do that to match your OpenCL headers' version.

Related

Why g++/clang++ throw error "does not give a valid preprocessing token"

Below is minimal code to reproduce problem.
#include <chrono>
#include <functional>
#include <iostream>
using namespace std;
class Test {
public:
Test() {}
void test1() { cout << __func__ << endl; }
void test2() { cout << __func__ << endl; }
void testPrepare() { cout << __func__ << endl; }
private:
};
#define DO_TEST(obj, testName) \
{ \
obj.testPrepare(); \
std::function<void(void)> test = std::bind(&Test::##testName, obj); \
/*test(); \
Some other code which use test()*/ \
}
int main(int argc, char const *argv[]) {
Test obj;
DO_TEST(obj, test1);
DO_TEST(obj, test2);
/* code */
return 0;
}
This works well and doing what is expected with cl.exe, but on g++/clang++ throwing a compile time error, as seen below:
g++ d.cpp
d.cpp:19:53: error: pasting "::" and "test1" does not give a valid preprocessing token
19 | std::function<void(void)> test = std::bind(&Test::##testName, obj); \
| ^~
d.cpp:26:3: note: in expansion of macro ‘DO_TEST’
26 | DO_TEST(obj, test1);
| ^~~~~~~
d.cpp:19:53: error: pasting "::" and "test2" does not give a valid preprocessing token
19 | std::function<void(void)> test = std::bind(&Test::##testName, obj); \
| ^~
d.cpp:27:3: note: in expansion of macro ‘DO_TEST’
27 | DO_TEST(obj, test2);
| ^~~~~~~
Compiler details:
cl.exe Microsoft (R) C/C++ Optimizing Compiler Version 19.29.30133 for x86
clang++ version 10.0.0-4ubuntu1, Target: x86_64-pc-linux-gnu
g++ (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
Note: I do know that changing &Test::##testName to &Test:: testName would solve the issue. But I want to understand whether it's bug of cl.exe to allow the code above or if g++/clang++ throwing an error is a bug.
According to the C spec:
each instance of a ## preprocessing token
in the replacement list is deleted and the preceding preprocessing
token is concatenated with the following preprocessing token. ...
If the result is not a valid preprocessing token, the behavior is undefined.
So using ## in such a way as to not create a single token is undefined -- the compiler can give a diagnostic about it, but is not required to, and it can instead (as an extension) do something else.

Expected unqualified-id before '&' token (Mininet VM, try/catch on std::invalid_argument)

I am getting the following error when compiling on the Mininet virtual machine using g++.
error: expected unqualified-id before '&' token
} catch (const std::invalid_argument& ia) {
^
Code:
try {
port = std::stoi(argv[3]);
if (port < 1024 || port > 65535) {
cerr << "Error: port number must be in the range 1024 to 65535";
exit(1);
}
} catch (const std::invalid_argument& ia) {
cerr << "Error: missing or additional arguments: Expected number for port" << endl;
}
I do not get the error when compiling on macOS with the same settings. Removing const or the & simply results in another error; doing std::invalid_argument ia results in "error: expected type-specifier"
Since I can't replicate this on my mac and this only occurs on the Mininet VM, I am at a loss as to the cause and potential fixes.
Note: To clarify, I ran sudo apt-get install g++ on the virtual machine today, and I am compiling with C++11 using the following: `g++ -std=c++11 -Wall -Wextra -pedantic -O -o code_name code_name.cpp
On Mininet's VM, #include <stdexcept> is required in order to use the functionality detailed in the question. This include file (among others) is not necessary on macOS, where it is included by default.
#include <stdexcept> fixes this specific problem.

Re-declaration of cmath functions in CUDA's math_functions.h

I included “cuda_runtime.h” in my project. It then raises compilation error:
In file included from /usr/local/cuda/include/common_functions.h:235:0,
from /usr/local/cuda/include/cuda_runtime.h:116,
from /usr/local/include/caffe2/core/common_gpu.h:7,
from /home/vpe.cripac/projects/LaS-VPE-Platform/src/native/DeepMAR_deploy/src/DeepMARCaffe2Utils.cpp:8:
/usr/local/cuda/include/math_functions.h:9421:99: error: redeclaration ‘float std::tanh(float)’ differs in ‘constexpr’
extern __DEVICE_FUNCTIONS_DECL__ __cudart_builtin__ __CUDA_CONSTEXPR__ float __cdecl tanh(float);
In file included from /usr/local/cuda/include/math_functions.h:8809:0,
from /usr/local/cuda/include/common_functions.h:235,
from /usr/local/cuda/include/cuda_runtime.h:116,
from /usr/local/include/caffe2/core/common_gpu.h:7,
from /home/vpe.cripac/projects/LaS-VPE-Platform/src/native/DeepMAR_deploy/src/DeepMARCaffe2Utils.cpp:8:
/usr/include/c++/4.8.2/cmath:520:3: error: from previous declaration ‘constexpr float std::tanh(float)’
tanh(float __x)
This happens both on Ubuntu and CentOS 7, using GCC 4.8.5 or 5.3.1.
Should I include any other header or define any macro before “cuda_runtime.h”?
You should never import math_functions.h into plain host code, and with g++ 4.8.5, I get an #error generated from within the header file if I try to do so. If you import cuda_runtime.h into your host code correctly, it will never import math_functions.h incorrectly:
$ cat test_math.cpp
#include <iostream>
#include <cmath>
#ifdef __BREAK_ME__
#include <math_functions.h>
#else
#include <cuda_runtime.h>
#endif
int main()
{
const float val = 0.123456789f;
std::cout << "tanh(" << val << ")=" << std::tanh(val) << std::endl;
return 0;
}
$ g++ -I/opt/cuda-8.0/include test_math.cpp
$ g++ -I/opt/cuda-8.0/include -D__BREAK_ME__ test_math.cpp
In file included from /opt/cuda-8.0/include/math_functions.h:10055:0,
from test_math.cpp:5:
/opt/cuda-8.0/include/crt/func_macro.h:50:2: error: #error -- incorrect inclusion of a cudart header file
#error -- incorrect inclusion of a cudart header file
^

Forcing a call to a class operator== to fail if return value is unused on GCC 4.4.7

I would like to know if there is a way to turn the use of a operator== on a class into a compiler error if the result is doing nothing with the result. The reason is to catch a use of the operator== when instead the developer intends to use operator=.
I do not care if the solution is GCC specific, as long as it works on GCC 4.4.7. Solutions can include GCC-specific attributes, compiler pragmas, or a source code file changes on the C++ class given below. Less attractive are changes to compiler options.
See example below. Uncomment the #define DO_STRING_LITERAL_TEST line below and you will see a helpful message from the compiler:
/usr/bin/g++ -MD -DDEBUG -g -ggdb -gstabs+ -O0 -fPIC -Wall -Werror -Wsynth -Wno-comment -Wreturn-type main.cpp -c -o main.o
cc1plus: warnings being treated as errors
main.cpp: In function ‘int main(int, char**, char* const*)’:
main.cpp:37: error: comparison with string literal results in unspecified behaviour
Comment the #define DO_STRING_LITERAL_TEST line, but then uncomment the #define DO_STRING_CONTAINER_TEST line. This compiles just fine and I would like it to fail on the line indicated:
foo == " "; // <-- I need this to throw a compiler error
Here is the example code:
#include <iostream>
#include <string>
class StringContainer {
private:
std::string _val;
public:
StringContainer(const char * inString = NULL) : _val(inString ? inString : "") {}
bool operator==(const StringContainer & other) const
{
return _val == other._val;
}
void operator=(const char * other)
{
_val = other;
}
const char * getString() const
{
return _val.c_str();
}
};
int main(int argc, char *argv[], char *const envp[])
{
std::cout << __FILE__ << ":" << __LINE__ << ":" << "main begin" << std::endl;
#define DO_STRING_LITERAL_TEST
#ifdef DO_STRING_LITERAL_TEST
const char * invalidval = "foo bar";
// The following use of == throws a nice compiler error on GCC 4.4.7:
invalidval == " ";
#endif // DO_STRING_LITERAL_TEST
//#define DO_STRING_CONTAINER_TEST
#ifdef DO_STRING_CONTAINER_TEST
StringContainer foo;
foo = "some string";
foo == " "; // <-- I need this to throw a compiler error
std::cout << __FILE__ << ":" << __LINE__ << ":" << "foo contains <" << foo.getString() << ">" << std::endl;
#endif // DO_STRING_CONTAINER_TEST
std::cout << __FILE__ << ":" << __LINE__ << ":" << "main end" << std::endl;
return 0;
} // end main
One answer came very close is at https://stackoverflow.com/a/12416677/257924 . But that specifies use of a function attribute, which looks quite attractive, however the version of the GCC compiler that I am required to use balks at the use of -Werror=unused-result:
cc1plus: error: -Werror=unused-result: No option -Wunused-result
If there was a source-code-only change that temporarily (for some segment of code, perhaps) the unused-result warning, that would be even better. https://freeswitch.org/jira/browse/FS-6850#commentauthor_55299_verbose apparently indicates that "same test with gcc 4.8.3 passes ok, since it supports the param."
This shouldn't be something you verify in code. This should be something that your compiler will do for you. If you need a std::string, you should use a std::string - not a MyStringThatHasThisExtraEqualityCheck.
I'd suggest one of several things:
Bug your favorite gcc developer to get them to implement -Wunused-comparison as per this bug report
Just compile your code with clang, which does support that warning. You can then add -Werror to make it an error. You don't need to run the clang binary, but an extra orthogonal couldn't hurt (just gives you more excuse to slack off).
Use some external static analysis tool to verify this stuff for you.
Write unit tests.
GCC allows the __attribute_warn_unused_result__ on a function. Have you tried it with your class's comparator?
EDIT: Never mind. Skipped over the section where you say that your old GCC version still does not support that attribute.

Boost compilation error

I am trying to compile my boost simple code:
#include <iostream>
#include <boost/thread.hpp>
void workerFunc(const char* msg, float delay_ms)
{
boost::posix_time::milliseconds workTime(delay_ms);
std::cout << "Worker: running, message = " << msg << std::endl;
// Pretend to do something useful...
boost::this_thread::sleep(workTime);
std::cout << "Worker: finished" << std::endl;
}
int main(int argc, char* argv[])
{
std::cout << "main: startup" << std::endl;
boost::thread workerThread(workerFunc, "Hello, Boost!", 2.5e3);
std::cout << "main: waiting for thread" << std::endl;
workerThread.join();
std::cout << "main: done" << std::endl;
return 0;
}
using g++ with this command
g++ main.cpp -o main
but i get an error like this:
main.cpp: In function `void workerFunc(const char*, float)':
main.cpp:7: error: `boost::posix_time' has not been declared
main.cpp:7: error: `milliseconds' was not declared in this scope
main.cpp:7: error: expected `;' before "workTime"
main.cpp:12: error: `boost::this_thread' has not been declared
main.cpp:12: error: `workTime' was not declared in this scope
main.cpp: In function `int main(int, char**)':
main.cpp:21: error: no matching function for call to `boost::thread::thread(void (&)(const char*, float), const char[14], double)'
/usr/include/boost/thread/thread.hpp:35: note: candidates are: boost::thread::thread(const boost::thread&)
/usr/include/boost/thread/thread.hpp:38: note: boost::thread::thread(const boost::function0<void, std::allocator<boost::function_base> >&)
/usr/include/boost/thread/thread.hpp:37: note: boost::thread::thread()
What's wrong and how should i compile it...?
According to this
http://www.boost.org/doc/libs/1_45_0/doc/html/date_time/posix_time.html
You need this
#include "boost/date_time/posix_time/posix_time.hpp"
I suspect you have an old version of Boost installed in your system. Read the file /usr/include/boost/version.hpp. And depending on which version you have, consult the version specific documentation (see Boost Documentation). Or install the latest version of Boost by either using you system's packaging functionality, if available, or manually following the install directions (see Getting Started on Unix Variants).
Since the compiler doesn't recognize some type, it means that you are missing some includes.
For posix_time you need to add #include "boost/date_time/posix_time/posix_time.hpp" on top of your code.
You need to include the header declaring posix_time. Look at the boost doc to see which it is (you can try #include "boost/date_time/posix_time/posix_time_system.hpp" but I'm not sure that would be enough).