I use an Arduino Uno with Arduino IDE 1.8.3. I have two arrays. I want to write a Deputy function that can add two arrays, and return the result to the main function and print it.
But I want to use x(sizeof(a)), but it seems not correct...
How do I solve this problem?
This is my code:
int a[]={1,2,3,4,5,6},b[]={1,1,1,1,1,1};
void setup() {
Serial.begin(9600);
int *p;
p = add(a,b);
for(int i=0;i<4;i++){
Serial.print(*(p+i));
}
}
void loop() {
}
int * add(int *a,int *b) {
int x = sizeof(a);
int y = sizeof(b);
static int z[4];
for(int i=0;i<4;i++) {
z[i]=a[i]+b[i];
}
return z;
}
int* a does not know the size of the array.
Easiest pass it as an extra parameter.
The next problem is that your static result cannot change its size dynamically.
static has additional problems anyway, in general.
int* add(const int *a,const int *b, int* result, byte size) {
for(byte i=0; i<size; i++) {
result[i]=a[i]+b[i];
}
return result;
}
Returning the result as the return value may be convenient.
Related
From this question and this question I managed to compile a minimal example of summing a vector into a single double inside OpenCL 1.2.
/* https://suhorukov.blogspot.com/2011/12/opencl-11-atomic-operations-on-floating.html */
inline void AtomicAdd(volatile __global double *source, const double operand) {
union { unsigned int intVal; double floatVal; } prevVal, newVal;
do {
prevVal.floatVal = *source;
newVal.floatVal = prevVal.floatVal + operand;
} while( atomic_cmpxchg((volatile __global unsigned int *)source, prevVal.intVal, newVal.intVal) != prevVal.intVal );
}
void kernel cost_function(__constant double* inputs, __global double* outputs){
int index = get_global_id(0);
if(0 == error_index){ outputs[0] = 0.0; }
barrier(CLK_GLOBAL_MEM_FENCE);
AtomicAdd(&outputs[0], inputs[index]); /* (1) */
//AtomicAdd(&outputs[0], 5.0); /* (2) */
}
As in fact this solution is incorrect because the result is always 0 when the buffer is accessed. What might the problem with this?
the code at /* (1) */ doesn't work, and neither does the code at /* (2) */, which is only there to test the logic independent of any inputs.
Is barrier(CLK_GLOBAL_MEM_FENCE); used correctly here to reset the output before any calculations are done to it?
According to the specs in OpenCL 1.2 single precision floating point numbers are supported by atomic operations, is this(AtomicAdd) a feasible method of extending the support to double precision numbers or am I missing something?
Of course the device I am testing with supports cl_khr_fp64˙of course.
Your AtomicAdd is incorrect. Namely, the 2 errors are:
In the union, intVal must be a 64-bit integer and not 32-bit integer.
Use the 64-bit atom_cmpxchg function and not the 32-bit atomic_cmpxchg function.
The correct implementation is:
#pragma OPENCL EXTENSION cl_khr_int64_base_atomics : enable
inline void AtomicAdd(volatile __global double *source, const double operand) {
union { unsigned ulong u64; double f64; } prevVal, newVal;
do {
prevVal.f64 = *source;
newVal.f64 = prevVal.f64 + operand;
} while(atom_cmpxchg((volatile __global ulong*)source, prevVal.u64, newVal.u64) != prevVal.u64);
}
barrier(CLK_GLOBAL_MEM_FENCE); is used correctly here. Note that a barrier must not be in an if- or else-branch.
UPDATE: According to STREAMHPC, the original implementation you use is not guaranteed to produce correct results. There is an improved implementation:
void __attribute__((always_inline)) atomic_add_f(volatile global float* addr, const float val) {
union {
uint u32;
float f32;
} next, expected, current;
current.f32 = *addr;
do {
next.f32 = (expected.f32=current.f32)+val; // ...*val for atomic_mul_f()
current.u32 = atomic_cmpxchg((volatile global uint*)addr, expected.u32, next.u32);
} while(current.u32!=expected.u32);
}
#ifdef cl_khr_int64_base_atomics
#pragma OPENCL EXTENSION cl_khr_int64_base_atomics : enable
void __attribute__((always_inline)) atomic_add_d(volatile global double* addr, const double val) {
union {
ulong u64;
double f64;
} next, expected, current;
current.f64 = *addr;
do {
next.f64 = (expected.f64=current.f64)+val; // ...*val for atomic_mul_d()
current.u64 = atom_cmpxchg((volatile global ulong*)addr, expected.u64, next.u64);
} while(current.u64!=expected.u64);
}
#endif
My code looks something like this:
#define SIZE_OF_ARRAY 1000
const long myArray[SIZE_OF_ARRAY] PROGMEM = {
1610514120L,
1613070480L,
1615630980L,
1618194720L,
1620759660L,
1623322440L,
1625879820L,
1628430600L,
1630975920L,
1633518300L,
1636060500L,
1638603840L,
1641148500L,
1643694540L,
... // All the way to 1000 elements
}
void setup() {
Serial.begin(115200);
for( int i = 0; i < SIZE_OF_ARRAY; i++){
long currentNumber = myArray[i];
// These also do not work:
//long currentNumber = pgm_read_word_near(myArray + i);
//long currentNumber = pgm_read_dword_near(myArray + i);
Serial.println(currentNumber);
}
}
But when I run this code, I get completely random junk data:
0
65536
0
-1195853640
8843185
-566231498
-310626819
-854754529
263210495
-325068311
-159567983
-1770239
-29784074
1054840810
-293611553
-436273185
-566231498
-310626819
-854754529
263210495
... all the way up to 1000
How can I access that array to get the data I put in it? I am not very familiar with C and the difference between variables and pointers, but it works without the PROGMEM flag so I assumed it would work with it as well.
Looks like the answer was to use:
void setup() {
Serial.begin(115200);
for( int i = 0; i < SIZE_OF_ARRAY; i++){
unsigned long currentNumber = pgm_read_dword_near(myArray + i);
Serial.println(currentNumber);
}
}
And to redefine the long array as:
const unsigned long myArray[SIZE_OF_ARRAY] PROGMEM = {
1610514120UL,
1613070480UL,
1615630980UL,
1618194720UL,
1620759660UL,
...
}
Because I was also running into long overflow errors
Hi trying to learn C specifically how to use pointers.
I wrote this script to practice ideas I've learned, but it crashes with segmentation fault error.
Bit of research search suggests that I am trying to access something that I should not be accessing I think that is an uninitialized pointer but I can't find it.
#include <stdio.h>
struct IntItem {
struct IntItem* next;
int value;
};
struct IntList {
struct IntItem* head;
struct IntItem* tail;
};
void append_list(struct IntList* ls, int item){
struct IntItem* last = ls->tail;
struct IntItem addition = {NULL,item};
last->next = &addition;
ls->tail = &addition;
if (!ls->head) {
ls->head = &addition;
}
}
int sum(int x, int y){
return x + y;
}
int max(int x, int y){
return x*(x>y) + y*(y>x);
}
int reduce(struct IntList xs, int (*opy)(int, int)){
struct IntItem current = *xs.head;
int running = 0;
while (current.next) {
running = opy(running,current.value);
current = *current.next;
}
return running;
}
int main(void) {
struct IntList ls = {NULL, NULL};
printf("Start Script\n");
append_list(&ls, 1);
append_list(&ls, 2);
append_list(&ls, 3);
printf("List Complete\n");
printf("Sum: %i",reduce(ls,sum));
printf("Max: %i",reduce(ls,max));
return 0;
}
Hints:
When you call append_list(&ls, 1), then inside append_list, what is the value of last?
What does last->next = &addition do?
And for your next bug:
What happens to addition after append_list returns? What does that mean for pointers to it?
Since Kernel Code in PyOpenCl needs to be written only in C, I have written few functions that need to be called inside the Kernel code in PyOpenCL.Where should I store these functions? how to pass a global variable to that function.
In PyOpenCl my kernel code looks like this:
program = cl.Program(context, """
__kernel void Kernel_OVERLAP_BETWEEN_N_IP_GPU(__constant int *FBNs_array,__local int *Binary_IP, __local int *cc,__global const int *olp)
{
function1(int *x, int *y,__global const int *olp);
}
""").build()
Where should I write and store the function1 function. should I define it in kernel itself, or in some other file and provide a path. If i need to define it at some other place and provide a path, please provide me some details , I am completely new to C.
Thanks
Like in C, before the kernel.
program = cl.Program(context, """
void function1(int *x, int *y)
{
//function1 code
}
__kernel void kernel_name()
{
function1(int *x, int *y);
}""").build()
program = cl.Program(context, """
void function1(int x, int *y,__global const int *cc)
{
x=10;
}
__kernel void kernel_name(__global const int *cc)
{
int x=1;
int y[1]={10};
function1(x,y,cc); //now x=10
}""").build()
The code below gives the error:
sketch_jul05a:2: error: variable or field 'func' declared void
So my question is: how can I pass a pointer to a struct as a function parameter?
Code:
typedef struct
{ int a,b;
} Struc;
void func(Struc *p) { }
void setup() {
Struc s;
func(&s);
}
void loop()
{
}
The problem is, that the Arduino-IDE auto-translates this into C like this:
#line 1 "sketch_jul05a.ino"
#include "Arduino.h"
void func(Struc *p);
void setup();
void loop();
#line 1
typedef struct
{ int a,b;
} Struc;
void func(Struc *p) { }
void setup() {
Struc s;
func(&s);
}
void loop()
{
}
Which means Struc is used in the declaration of func before Struc is known to the C compiler.
Solution: Move the definition of Struc into another header file and include this.
Main sketch:
#include "datastructures.h"
void func(Struc *p) { }
void setup() {
Struc s;
func(&s);
}
void loop()
{
}
and datastructures.h:
struct Struc
{ int a,b;
};
The answer above works. In the meantime I had found the following also to work, without the need for a .h file:
typedef struct MyStruc
{ int a,b;
} Struc;
void func(struct MyStruc *p) { }
void setup() {
Struc s;
func(&s);
}
void loop()
{
}
Be warned: Arduino coding is a little flaky. Many of the libraries are also a bit flaky!
This next code works for me as in Arduino 1.6.3:
typedef struct S
{
int a;
}S;
void f(S * s, int v);
void f(S * s, int v)
{
s->a = v;
}
void setup() {
}
void loop() {
S anObject;
// I hate global variables
pinMode(13, OUTPUT);
// I hate the "setup()" function
f(&anObject, 0);
// I love ADTs
while (1) // I hate the "loop" mechanism
{
// do something
}
}
Prolly old news, but typedef struct allows member functions (at least in IDE 1.6.4). Depending on what you want to do, of course, but I can't think of any func(struct *p) that couldn't be handled also with object.func(param pdata). Just that something like p->a = 120; becomes something like object.setA(120);
typedef struct {
byte var1;
byte var2;
void setVar1(byte val){
this->var1=val;
}
byte getVar1(void) {
return this->var1;
}
} wtf;
wtf testW = {127,15};
void initwtf(byte setVal) {
testW.setVar1(setVal);
Serial.print("Here is an objective returned value: ");
Serial.println(testW.getVar1());
}
...
void loop() {
initwtf(random(0,100));
}