Open MP: private structure with shared element? - openmp

Is the following possible?
EDIT: Minimal working example:
#include <omp.h>
#include <stdio.h>
struct foo
{
int a;
int b;
};
int main(int argc, char ** argv)
{
struct foo outerFoo;
int * p = &outerFoo.a;
outerFoo.a = 1;
printf("outerFoo # %p, a=%d\n", &outerFoo, outerFoo.a);
#pragma omp parallel private(outerFoo), shared(p)
{
printf("Thread %d: outerFoo # %p, a=%d, p = %p,p->:%d\n",
omp_get_thread_num(),
&outerFoo, outerFoo.a,p,*p);
#pragma omp critical // i know i can use atomic here
{
*p=*p+1;
}
}
printf("a:%d\n",outerFoo.a);
return 0;
}

What you have written is certainly possible. Whether it does what you want is impossible for us to tell, since you haven't told us what that is!
I strongly suspect that it doesn't, since it will generate new, uninitialized instances of somestruct in each thread, and a shared pointer to the outer scope instance.
Consider this code which is effectively the same as yours, but compileable
#include <omp.h>
#include <cstdio>
class foo
{
public:
int a;
int b;
foo() : a(0), b(1) {}
};
int main(int argc, char ** argv)
{
foo outerFoo;
int * p = &outerFoo.a;
outerFoo.a = 27;
printf("outerFoo # %p, a=%d, b=%d\n", &outerFoo, outerFoo.a, outerFoo.b);
#pragma omp parallel private(outerFoo), shared(p)
{
printf("Thread %d: outerFoo # %p, a=%d, b=%d, p = %p\n",
omp_get_thread_num(),
&outerFoo, outerFoo.a, outerFoo.b,p);
}
return 0;
}
It prints something like this
OMP_NUM_THREADS=4 ./a.out
outerFoo # 0x7fffffffd080, a=27, b=1
Thread 0: outerFoo # 0x7fffffffcb80, a=0, b=1, p = 0x7fffffffd080
Thread 3: outerFoo # 0x2aaaacf4fa80, a=0, b=1, p = 0x7fffffffd080
Thread 2: outerFoo # 0x2aaaacb4da80, a=0, b=1, p = 0x7fffffffd080
Thread 1: outerFoo # 0x2aaaac74ba00, a=0, b=1, p = 0x7fffffffd080
So you can see that happening. There is one outer instance of the class and four inner ones. All of them have all of the struct fields.

Related

how to convert char ** to unique_ptr array?

The old code is as below:
char** wargv = new char*[argc];//memory leak!
for(int k = 0; k < argc; ++k)
{
wargv[k] = new char[strlen(argv[k]) + 1];
strncpy(wargv[k], argv[k], strlen(argv[k]));
wargv[k][strlen(argv[k])] = '\0';
}
because there may cause memory leak, so I want to convert wargv to unique_ptr. How to make it?
I know how to convert char* to unique_ptr, the code below works:
int size_t = 10;
std::unique_ptr<char[]> wargv(new char[size_t]{0});
strncpy(wargv.get(), "abcdef", size_t);
but I don't know how to convert char ** to unique_ptr, I tried vector,but it doesn't work.
As #Some programmer dude commented, std::vector<std::string> should be a better choice than std::unique_ptr<>, with memory allocation management.
I try to write a simple example and it works well.
#include <iostream>
#include <string>
#include <vector>
int main(int argc, char** argv) {
std::vector<std::string> collection(argc);
for (auto i = 0; i < argc; i++) {
collection[i] = argv[i];
}
for (const auto& arg : collection) {
std::cout << arg << "\n";
}
}

Creating a parallel arithmetic operator in an infinite loop in C compiler on Mac Terminal

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
void main (void)
{
while(1) // infinite loop
{
int a, b;
printf("Give me an integer a: ");
scanf("%d",&a);
printf("Give me an integer b: ");
scanf("%d",&b);
sum = &a + &b;
product = &a * &b;
difference = &a - &b;
echo Here is your sum, product, and difference:
printf("Sum: %d + d% = %d.\n", a, b, sum);
printf("Product: %d * d% = %d.\n", a, b, product);
printf("Difference: %d - d% = %d.\n", a, b, difference);
return 0;
}
}
I keep getting a syntax error with my void main (void) on line 6
Using child processes to create 3 parallel processes.
This program has a bunch of problems, and it's not doing anything in parallel:
void main (void)
This will usually compile, but according to the C standard it's not correct. The signature of main() that takes no arguments should be int main(void).
sum = &a + &b;
product = &a * &b;
difference = &a - &b;
You're using the addresses of a and b instead of the values, so you'd always get the same results for sum, product, and difference (except that didn't define the last three.) The correct version should be:
sum = a + b;
product = a * b;
difference = a - b;
echo Here is your sum, product, and difference:
This isn't a C construct, so the compiler will complain about this. Use printf().
return 0;
Although you've indicated that the loop should be infinite, it won't be because you exit the function at the end of the loop.

Effective implementation of conversion small string to uint64_t

#include <cstdint>
#include <cstring>
template<typename T>
T oph_(const char *s){
constexpr std::size_t MAX = sizeof(T);
const std::size_t size = strnlen(s, MAX);
T r = 0;
for(auto it = s; it - s < size; ++it)
r = r << 8 | *it;
return r;
}
inline uint64_t oph(const char *s){
return oph_<uint64_t>(s);
}
int main(){
uint64_t const a = oph("New York City");
uint64_t const b = oph("Boston International");
return a > b;
}
I want to convert first 8 characters from const char * to uint64_t so I can easily compare if two strings are greater / lesser.
I am aware that equals will semi-work.
However I am not sure if this is most efficient implementation.
I want the implementation to work on both little and big endian machines.
This is a C implementation, that should be faster that your implementation, but I still need to use strncpy which should be the bottleneck
#include <string.h>
#include <stdio.h>
#include <stdint.h>
#include <byteswap.h>
union small_str {
uint64_t v;
char buf[8];
};
static uint64_t fill_small_str(const char *str)
{
union small_str ss = { 0 };
strncpy(ss.buf, str, 8);
#if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
return ss.v;
#else
return bswap_64(ss.v);
#endif
}
int main(void)
{
uint64_t const a = fill_small_str("Aew York City");
uint64_t const b = fill_small_str("Boston International");
printf("%lu ; %lu ; %d\n", a, b, (a < b));
return 0;
}

Thread safe counter using OpenMP

What are solutions to the hazards in doing this?
#include <iostream>
#include <unistd.h>
#include <cstdlib>
#include <ctime>
int main(){
int k = 0;
#pragma omp parallel for
for(int i = 0; i < 100000; i++){
if (i % 2){ /** Conditional based on i **/
#pragma omp atomic
k++;
usleep(1000 * ((float)std::rand() / RAND_MAX));
#pragma omp task
std::cout << k << std::endl; /** Some sort of task **/
}
}
return 0;
}
I need all ks to be unique. What would be a better way of doing this?
Edit
Notice how this question refers to an aggregate
In particular I want to spawn tasks based on a shared variable. I run the risk of having a race condition.
Consider thread 2 completes, evaluates true for the conditional, and increments k before thread 1 spawns all tasks.
Edit edit
I tried to force a race condition. It wasn't obvious without the sleep. There are in fact problems. How can I overcome this.
Here's a quick solution:
...
#pragma omp atomic
k++;
int c = k;
...
but I'd like a guarantee.
Tangential. Why doesn't this implementation work?
...
int c;
#pragma omp crtical
{
k++;
c = k;
}
...
At the end of the function, std::cout << k;, is consistently less than the expected 50000 output proof
I hate to answer my question so quickly, but I found a solution for this particular instance.
As of OpenMP 3.1 there is the "atomic capture" pragma
The use case is for problems just like this. The resultant code:
#include <iostream>
#include <unistd.h>
#include <cstdlib>
#include <ctime>
int main(){
int k = 0;
#pragma omp parallel for
for(int i = 0; i < 100000; i++){
if (i % 2){ /** Conditional based on i **/
int c;
#pragma omp atomic capture
{
c = k;
k++;
}
usleep(1000 * ((float)std::rand() / RAND_MAX));
#pragma omp task
std::cout << c << std::endl; /** Some sort of task **/
}
}
std::cout << k << std::endl; /** Some sort of task **/
std::cout.flush();
return 0;
}
I will leave this problem open if someone would like to contribute ideas/ code arch. suggestions for avoiding these problems, reasons the #pragma omp crtical didn't work

Why does the left shift on a unsigned int happens from the 16th bit?

I am trying to put the values from the vector into the int.
Given vector :'1','0','1','1','1','0','1','1','1','0','1','1','1','0','1','1' :
Expected output (binary representation for the variable out):
00000000000000001011101110111011.
However, I am getting the following output:
10111011101110110000000000000000
Notice: the insertion begun at the 16bit from right end instead of beginning from the leftmost bit
#include<vector>
#include<iostream>
int main() {
std::vector<unsigned char> test = {'1','0','1','1','1','0','1','1','1','0','1','1','1','0','1','1'};
std::vector<unsigned int> out(1);
int j = 0;
for (int i =0; i < test.size(); i++) {
out[j] = out[j] << 1;
if (test[i] == '1') {out[j] |=0x1;}
}
j++;
for (int p = 0; p < j; p++) {
for (int k = 0; k<32; k++ ) {
std::cout << !!((out[p]<<k)&0x8000);
}
std::cout << std::endl;
}
std::cout << "Size Of:" << sizeof(int);
return 0;
}
The reason why this happens is that you are using a wrong constant for the mask: 0x8000 has its 16-bit set, while you probably meant to use 0x80000000 with the 32-nd bit set. To avoid mistakes like that it's best to construct masks with shifts, for example
(1 << 31)
This expression is evaluated at compile time, so the result is the same as if you computed the constant yourself.
Note that both 0x8000 and 0x80000000 constants are system-dependent. Moreover, 0x80000000 assumes 32-bit int, which is not guaranteed.
A better approach would be shifting the number right instead of left, and masking with 1.
The block of code creating out[j] works just fine.
Your problem is in the output block, due to use of 0x8000. Whenever k >= 16, the low 16 bits will be zero, guaranteeing that 0x8000 is zero.
Your code seems overly complicated to me. Here's my version of a C program that transforms a string of 1's and 0's into an int and one going from int to string.
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv);
int main (int argc, char **argv) {
char str [] = "1010101010101010";
int x;
int out;
for (x=0;x<16;x++) {
if (str[x] == '1') {
out |= (1 << x);
}
}
printf("%d", out) ;
}
and
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv);
int main (int argc, char **argv) {
char str [] = "1010101010101010";
int in = 21845;
char out[17] = {0};
for (x=0;x<16;x++) {
if (in & (1<<x)) {
out[x] = '1';
}
else {
out[x] = '0';
}
}
printf("%s", out) ;
}

Resources