OpenCL Kernel code compile error - Visual Studio 2019 - opencl

I'm kind of new to OpenCL programming and am trying to run a simple vector addition code in VS 2019. However, I can't get the .cl code to compile. It's showing these 6 errors when trying to build the program:
Error C2144 syntax error: 'void' should be preceded by ';'
Error C4430 missing type specifier - int assumed. Note: C++ does not support default-int
Error C2065 '__global': undeclared identifier
Error C2146 syntax error: missing ')' before identifier 'float4'
Error C2143 syntax error: missing ';' before '{'
Error C2447 '{': missing function header (old-style formal list?)
This is my kernel code:
__kernel void add_numbers(__global float4* data,
__local float* local_result, __global float* group_result) {
float sum;
float4 input1, input2, sum_vector;
uint global_addr, local_addr;
global_addr = get_global_id(0) * 2;
input1 = data[global_addr];
input2 = data[global_addr + 1];
sum_vector = input1 + input2;
local_addr = get_local_id(0);
local_result[local_addr] = sum_vector.s0 + sum_vector.s1 +
sum_vector.s2 + sum_vector.s3;
barrier(CLK_LOCAL_MEM_FENCE);
if (get_local_id(0) == 0) {
sum = 0.0f;
for (int i = 0; i < get_local_size(0); i++) {
sum += local_result[i];
}
group_result[get_group_id(0)] = sum;
}
}
I have added the include and lib directories and linked them properly. I couldn't find many fixes for this error after googling. Please help me out...
UPDATE : I fixed it
Hello everyone,
I found the solution to this problem. I removed the .cl file from VS projects and then re-added it (optional). I also changed file open option to have "rb" instead of "r" ( fopen(filename,"rb") ). Now I'm able to run it!

Your issue was that the C++ compiler wanted to compile the OpenCL code. You can exclude the file from the VS project and read it with fstream at runtime to get the kernel code string, or you can embed the kernel code string right into the executable via stringification macro:
#include <string>
#define R(...) string(" "#__VA_ARGS__" ")
string get_opencl_code() { return R(
// put your OpenCL C code here
);}

Related

Advice needed for migration of low level OpenSSL API to high level OpenSSL APIs

I am new to OpenSSL and is currently working on a C++ project that has a dependency on OpenSSL. Recently i started using a machine that had openSSL 3.0 installed but is unable to build the project because i get compiler errors like below ( please note that warnings are treated as error in the project)
error: 'MD5' is deprecated
if (!MD5((uint8_t*)key.data(), key.size(), hashOutput)) {
^
/usr/local/Cellar/openssl#3/3.0.0_1/include/openssl/md5.h:52:1: note: 'MD5' has been explicitly marked deprecated here
OSSL_DEPRECATEDIN_3_0 unsigned char *MD5(const unsigned char *d, size_t n,
^
/usr/local/Cellar/openssl#3/3.0.0_1/include/openssl/macros.h:182:49: note: expanded from macro 'OSSL_DEPRECATEDIN_3_0'
# define OSSL_DEPRECATEDIN_3_0 OSSL_DEPRECATED(3.0)
^
/usr/local/Cellar/openssl#3/3.0.0_1/include/openssl/macros.h:62:52: note: expanded from macro 'OSSL_DEPRECATED'
# define OSSL_DEPRECATED(since) __attribute__((deprecated))
^
1 error generated.
Doing some investigation i found that these API's were deprecated in OpenSSL 3.0.0 and now i have three options
Ignore the warnings. They are just warnings. The deprecated functions are still present and you may still use them. However be aware that they may be removed from a future version of OpenSSL.
Suppress the warnings. Refer to your compiler documentation on how to do this.
Remove your usage of the low level APIs. In this case you will need to rewrite your code to use the high level APIs instead.
I choose the third option but even after reading documentations related to OpenSSL, i am still not sure what is the EVP API equivalent of the MD5 method which got deprecated in OpenSSL 3.0.0. If you check the link https://www.openssl.org/docs/manmaster/man3/MD5.html it states that
All of the functions described on this page are deprecated.
Applications should instead use EVP_DigestInit_ex(3),
EVP_DigestUpdate(3) and EVP_DigestFinal_ex(3).
Would be great if someone can provide me some feedback/help or additional resources/links that might help me understand using the high Level OpenSSL API's in general so that i can make it work for my use case i.e MD5 encryption.
I must also mention that i downloaded OpenSSL repo from github and found that the implementation of md5 method is as below
unsigned char *MD5(const unsigned char *d, size_t n, unsigned char *md)
{
MD5_CTX c;
static unsigned char m[MD5_DIGEST_LENGTH];
if (md == NULL)
md = m;
if (!MD5_Init(&c))
return NULL;
#ifndef CHARSET_EBCDIC
MD5_Update(&c, d, n);
#else
{
char temp[1024];
unsigned long chunk;
while (n > 0) {
chunk = (n > sizeof(temp)) ? sizeof(temp) : n;
ebcdic2ascii(temp, d, chunk);
MD5_Update(&c, temp, chunk);
n -= chunk;
d += chunk;
}
}
#endif
MD5_Final(md, &c);
OPENSSL_cleanse(&c, sizeof(c)); /* security consideration */
return md;
}
I hope this example would help (I'm not checking for errors and exceptions in my example, so be aware of that):
Deprecated Implementation
#include <openssl/md5.h>
static void calculate_md5(unsigned char* buf, unsigned int buf_size)
{
unsigned char md5_digest[MD5_DIGEST_LENGTH];
MD5_CTX md5ctx;
MD5_Init(&md5ctx);
MD5_Update(&md5ctx, buf, buf_size);
MD5_Final(md5_digest, &md5ctx);
}
New Implementation:
#include <openssl/evp.h>
static void calculate_md5(unsigned char* buf, unsigned int buf_size)
{
EVP_MD_CTX *mdctx;
unsigned char *md5_digest;
unsigned int md5_digest_len = EVP_MD_size(EVP_md5());
// MD5_Init
mdctx = EVP_MD_CTX_new();
EVP_DigestInit_ex(mdctx, EVP_md5(), NULL);
// MD5_Update
EVP_DigestUpdate(mdctx, buf, buf_size);
// MD5_Final
md5_digest = (unsigned char *)OPENSSL_malloc(md5_digest_len);
EVP_DigestFinal_ex(mdctx, md5_digest, &md5_digest_len);
EVP_MD_CTX_free(mdctx);
}

Error compiling VexCL program: raw_ptr not a member of device_vector

I am trying to compile my first VexCL program using the thrust example and I get the following error message:
raw_ptr is not a member of 'vex::backend::opencl::device_vector'
Here is the code
vex::Context ctx(vex::Filter::Env && vex::Filter::Count(1));
std::cout << ctx << std::endl;
vex::profiler<> prof(ctx);
typedef int T;
const size_t n = 16 * 1024 * 1024;
vex::vector<T> x(ctx, n);
vex::Random<T> rnd;
// Get raw pointers to the device memory.
T *x_begin = x(0).raw_ptr(); // Here is where the error is occurring.
T *x_end = x_begin + x.size();
I do not understand the language well enough. I appreciate any help in this matter.
Thanks
Chris
The thrust example is not the best to start with, as it deals with interfacing VexCL and Thrust (another high-level library that is targeted on CUDA).
So in order to compile the example, you need to use the CUDA backend in VexCL. That is, you need to define VEXCL_BACKEND_CUDA preprocessor macro
and to link against libcuda.so (or cuda.lib if on Windows) instead of libOpenCL.so/OpenCL.lib.
The error you got is because the device_vector class only exposes raw_ptr() method when on CUDA backend.

yylval undefined with lex and yacc

I was trying a simple program to create an abstract syntax tree using lex and yacc.
My yacc_file.y is
%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct node
{
struct node *left;
struct node *right;
char *token;
} node;
node *mknode(node *left, node *right, char *token);
void printtree(node *tree);
#define YYSTYPE struct node *
%}
%start lines
%token NUMBER
%token PLUS MINUS TIMES
%token LEFT_PARENTHESIS RIGHT_PARENTHESIS
%token END
%left PLUS MINUS
%left TIMES
%%
lines: /* empty */
| lines line /* do nothing */
line: exp END { printtree($1); printf("\n");}
;
exp : term {$$ = $1;}
| exp PLUS term {$$ = mknode($1, $3, "+");}
| exp MINUS term {$$ = mknode($1, $3, "-");}
;
term : factor {$$ = $1;}
| term TIMES factor {$$ = mknode($1, $3, "*");}
;
factor : NUMBER {$$ = mknode(0,0,(char *)yylval);}
| LEFT_PARENTHESIS exp RIGHT_PARENTHESIS {$$ = $2;}
;
%%
int main (void) {return yyparse ( );}
node *mknode(node *left, node *right, char *token)
{
/* malloc the node */
node *newnode = (node *)malloc(sizeof(node));
char *newstr = (char *)malloc(strlen(token)+1);
strcpy(newstr, token);
newnode->left = left;
newnode->right = right;
newnode->token = newstr;
return(newnode);
}
void printtree(node *tree)
{
int i;
if (tree->left || tree->right)
printf("(");
printf(" %s ", tree->token);
if (tree->left)
printtree(tree->left);
if (tree->right)
printtree(tree->right);
if (tree->left || tree->right)
printf(")");
}
int yyerror (char *s) {fprintf (stderr, "%s\n", s);}
My lex_file.l file is
%{
#include "yacc_file.tab.h"
%}
%%
[0-9]+ {yylval = (int)yytext; return NUMBER;}
/* cast pointer to int for compiler warning */
[ \t\n] ;
"+" return(PLUS);
"-" return(MINUS);
"*" return(TIMES);
"(" return(LEFT_PARENTHESIS);
")" return(RIGHT_PARENTHESIS);
";" return(END);
%%
int yywrap (void) {return 1;}
To run, I have done the following
yacc -d yacc_file.y
lex lex_file.y
cc y.tab.c lex.yy.c -o a.exe
I got the following error
lexfile.l: In function 'yylex':
lex_file.l:10:2: error: 'yylval' undeclared(first used in this function)
[0-9]+ {yylval=(int)yytext; return NUMBER;}
I have searched on google and %union seems to solve the problem. But I am not sure how to use it.
The command
yacc -d yacc_file.y
produces a header file called y.tab.h and a C file called y.tab.c. That's the yacc-compatible default naming, and it does not agree with your flex file, which is expecting the header to be called yacc_file.tab.h.
You could just change the #include statement in your flex file, but that wouldn't be compatible with the build system at your college. So I suggest you change to the command bison -d yacc_file.y instead of your yacc command. That will produce a header file called yacc_file.tab.h and a C file called yacc_file.tab.c. (Of course, you will then have to change the cc command to compile yacc_file.tab.c instead of y.tab.c.)
Presumably there is some incorrect yacc_file.tab.h on your machine, which doesn't include a declaration of yylval. Hence the compilation error.
To avoid confusing yourself further, when you fix your build procedure I'd recommend deleting all the intermediate files -- y.tab.h and y.tab.c as well as yacc_file.tab.c and yacc_file.tab.h, and lex.yy.c. Then you can do a clean build without having to worry about picking up some outdated intermediate file.
Also, in yacc_file.y, you #define YYSTYPE as struct node *. That's fine, but the #define will not be copied into the generated header file; in the header file, YYSTYPE will be #defined as int if there is no other #define before the header file is #included.
Moreover, in lex_file.l you use yylval as though it were an int (yylval = (int)yytext;) but I think that statement does not do what you think it does. What it does is reinterpret the address of yytext as an integer. That's legal but meaningless. What you wanted to do, I think, is to convert the string in yytext as an integer. To do that, you need to use strtod or some similar function from the standard C library.
Regardless, it is vital that the scanner and the parser agree on the type of yylval. Otherwise, things will go desperately wrong.
As you mention, it is possible to use a %union declaration to declare YYSTYPE as a union type. You should make sure you understand C union types, and also read the bison manual section on semantics..

force call to QString(const char *) constructor in Qt 4.7

I am trying to compile a library written in Qt 4.6. On my current Linux machine I have only Qt 4.7 installed. The following code part:
/*file try.h*/
void fileOpen(QString s = NULL) ;
/*file try.cpp*/
void MainWindow::fileOpen(QString s) {
QString filename ;
if(s.isNull()) filename = QFileDialog::getOpenFileName(
this,
"Choose a file",
".",
"Source file (*.)");
else filename = s ;
}
compiles with the following error (I used cmake but the corresponding line code is the one listed above):
In member function ‘virtual int MainWindow::qt_metacall(QMetaObject::Call, int,
void**)’:
/homes/combi/hodorog/Developments/axelOld/build/axel/src/QGui/moc_MainWindow.cxx:141:26:
error: conversion from ‘long int’ to ‘QString’ is ambiguous
/homes/combi/hodorog/Developments/axelOld/build/axel/src/QGui/moc_MainWindow.cxx:141:26:
note: candidates are:
/usr/include/QtCore/qstring.h:426:43: note: QString::QString(const char*)
/usr/include/QtCore/qstring.h:105:14: note: QString::QString(const QChar*)
So I am guessing the problem is that in qt. 4.7. there are two QString constructors that can take a pointer as an argument (as listed in the compilation error), whereas in qt 4.6. there is only one QString constructor that can take a pointer as an argument. How can I force QString to call the constructor with const char * as an argument?
Thank a lot for your help in advance,
madalina
void fileOpen(QString s = NULL);
You are trying to construct a QString object with 0. It seems you are confusing the null of pointers with a null QString. A null QString is one which is created with the constructor QString(). Given how your function is implemented (referring to s.isNull()), you should change the function declaration to
void fileOpen(QString s = QString());

QString string/text formatting

I am trying to format a QString using the arg() function as follows:
QColor color = QColorDialog::getColor(Qt::blue, this);
....
QString tStr = QString("R: %1 G: %2 B: %3").arg( color.red(), color.green(), color.blue());
Here I get a 'integer division by zero exception'.
Background: using Qt add-in in VS 2010. Brand new to Qt framework.
Any suggestions?
Thanks
You should change that line to
QString tStr = QString("R: %1 G: %2 B: %3")
.arg(color.red()).arg(color.green()).arg(color.blue());
I can only assume that your code is mapping to this overload of arg()
QString QString::arg(int a, int fieldWidth = 0, int base = 10,
const QChar & fillChar = QLatin1Char( ' ' )) const
I'm surprised that it is resulting in a division by zero error because nobody performs division without checking for 0 first or catching the exception :) Anyway, I ran a test here of your code on Qt 4.7.4 / Windows 7 / MinGW without an error, just the wrong result string.

Resources