What are the other options of faster IO in C - c

I implemented merge sort and used it as a solution for this codechef problem. Here are the submissions. The code is placed below.
The problem that I think is causing slow execution is that my IO is slow in the main function. I know the number of elements that are inputted so there has to be some faster way to read input instead of the way that I am doing.
Are there faster IO methods instead of the ones that I am using in the main function? I have heard about using buffers, fgets and sscanf but I don't know if they are faster.
Any code examples would be helpful.
#include<stdio.h>
#include<stdlib.h>
void merge_parts(int arr[], int length)
{
int *ans;
int i, j, k;
int temp = length/2;
ans = malloc(sizeof(int) * length);
//This while and next if-else puts the merged array into temporary array ans
for (j = temp, i = k = 0; (i < temp && j < length); k++){
ans[k] = (arr[i] < arr[j]) ? arr[i++] : arr[j++];
}
if(i >= temp){
while(j < length){
ans[k++] = arr[j++];
}
}
else{
while(i < temp){
ans[k++] = arr[i++];
}
}
//This while loops puts array ans into original array arr
for(i = 0; i < length; i++){
arr[i] = ans[i];
}
free(ans);
}
void merge_sort(int arr[], int length)
{
if(length > 1)
{
merge_sort(&arr[0], (length/2));
merge_sort(&arr[length/2], (length - length/2));
merge_parts(arr, length);
}
}
int main()
{
int length;
int *arr;
scanf("%d", &length);
arr = malloc(sizeof(int) * length);
for(int i = 0; i < length; i++)
scanf("%d", &arr[i]);
merge_sort(arr, length);
for(int i = 0; i < length; i++)
printf("%d ", arr[i]);
free(arr);
return 0;
}
EDIT3:
[I deleted EDIT AND EDIT2 as they were no longer relevant]
merge_sort algorithm that I am using
void merge_parts(int arr[], int length)
{
int ans[length];
int i, j, k;
int temp = length/2;
//This while and next if-else puts the merged array into temporary array ans
for (j = temp, i = k = 0; (i < temp && j < length); k++){
ans[k] = (arr[i] < arr[j]) ? arr[i++] : arr[j++];
}
if(i >= temp){
while(j < length){
ans[k++] = arr[j++];
}
}
else{
while(i < temp){
ans[k++] = arr[i++];
}
}
//This while loops puts array ans into original array arr
for(i = 0; i < length; i++){
arr[i] = ans[i];
}
}
void merge_sort(int arr[], int length)
{
if(length > 1)
{
merge_sort(&arr[0], (length/2));
merge_sort(&arr[length/2], (length - length/2));
merge_parts(arr, length);
}
}
merge1.c
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
#include<time.h>
#define SORTING_ALGO_CALL merge_sort
char buffer[4096];
int bufcount;
int bufpos;
int get_next_char()
{
if (!bufcount)
{
bufcount = fread(buffer, 1, 4096, stdin);
bufpos = 0;
if (!bufcount){
return EOF;
}
}
bufcount--;
return buffer[bufpos++];
}
int readnum()
{
int res = 0;
char ch;
do
{
ch = get_next_char();
} while (!isdigit(ch) && ch != EOF);
if (ch == EOF){
return 0xbaadbeef; // Don't expect this to happen.
}
do
{
res = (res * 10) + ch - '0';
ch = get_next_char();
} while(isdigit(ch));
return res;
}
int main()
{
clock_t time1, time2;
double time_taken;
//FIRST READ
time1 = clock();
int length = readnum();
while (length < 1)
{
printf("\nYou entered length = %d\n", length);
printf("\nEnter a positive length: ");
length = readnum();
}
//SECOND READ, PRINT AND NEXT FIRST READ
time2 = clock();
time_taken = (double)(time2 - time1) / CLOCKS_PER_SEC;
printf("\nReading length = %f\n", time_taken);
time1 = clock();
int *arr;
if ((arr = malloc(sizeof(int) * length)) == NULL)
{
perror("The following error occurred");
exit(-1);
}
//SECOND READ, PRINT AND NEXT FIRST READ
time2 = clock();
time_taken = (double)(time2 - time1) / CLOCKS_PER_SEC;
printf("\nAllocating array = %f\n", time_taken);
time1 = clock();
for (int i = 0; i < length; i++){
arr[i] = readnum();
}
//SECOND READ, PRINT AND NEXT FIRST READ
time2 = clock();
time_taken = (double)(time2 - time1) / CLOCKS_PER_SEC;
printf("\nReading array = %f\n", time_taken);
time1 = clock();
SORTING_ALGO_CALL(arr, length);
//SECOND READ, PRINT AND NEXT FIRST READ
time2 = clock();
time_taken = (double)(time2 - time1) / CLOCKS_PER_SEC;
printf("\nSorting array = %f\n", time_taken);
time1 = clock();
/*
for (int i = 0; i < length; i++){
printf("%d ", arr[i]);
}
*/
//SECOND READ, PRINT AND NEXT FIRST READ
time2 = clock();
time_taken = (double)(time2 - time1) / CLOCKS_PER_SEC;
printf("\nPrinting Sorted array = %f\n", time_taken);
time1 = clock();
free(arr);
//SECOND READ, PRINT
time2 = clock();
time_taken = (double)(time2 - time1) / CLOCKS_PER_SEC;
printf("\nFreeing array = %f\n", time_taken);
return 0;
}
merge2.c
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define SORTING_ALGO_CALL merge_sort
int main()
{
clock_t time1, time2;
double time_taken;
//FIRST READ
time1 = clock();
int length;
scanf("%d", &length);
while (length < 1)
{
printf("\nYou entered length = %d\n", length);
printf("\nEnter a positive length: ");
scanf("%d", &length);
}
//SECOND READ, PRINT AND NEXT FIRST READ
time2 = clock();
time_taken = (double)(time2 - time1) / CLOCKS_PER_SEC;
printf("\nReading length = %f\n", time_taken);
time1 = clock();
int *arr;
if ((arr = malloc(sizeof(int) * length)) == NULL)
{
perror("The following error occurred");
exit(-1);
}
//SECOND READ, PRINT AND NEXT FIRST READ
time2 = clock();
time_taken = (double)(time2 - time1) / CLOCKS_PER_SEC;
printf("\nAllocating array = %f\n", time_taken);
time1 = clock();
for (int i = 0; i < length; i++){
scanf("%d", &arr[i]);
}
//SECOND READ, PRINT AND NEXT FIRST READ
time2 = clock();
time_taken = (double)(time2 - time1) / CLOCKS_PER_SEC;
printf("\nReading array = %f\n", time_taken);
time1 = clock();
SORTING_ALGO_CALL(arr, length);
//SECOND READ, PRINT AND NEXT FIRST READ
time2 = clock();
time_taken = (double)(time2 - time1) / CLOCKS_PER_SEC;
printf("\nSorting array = %f\n", time_taken);
time1 = clock();
/*
for (int i = 0; i < length; i++){
printf("%d ", arr[i]);
}
*/
//SECOND READ, PRINT AND NEXT FIRST READ
time2 = clock();
time_taken = (double)(time2 - time1) / CLOCKS_PER_SEC;
printf("\nPrinting Sorted array = %f\n", time_taken);
time1 = clock();
free(arr);
//SECOND READ, PRINT
time2 = clock();
time_taken = (double)(time2 - time1) / CLOCKS_PER_SEC;
printf("\nFreeing array = %f\n", time_taken);
return 0;
}
Both merge1.c and merge2.c contain the 2 functions of merge-sort.
The file that I am using for generating worst-case(decreasing order) input for the 2 files.
#include<stdio.h>
int main()
{
int j = 100000;
printf("%d\n", j);
for(int i = j; i > 0; i--)
printf("%d\n", i);
return 0;
}
Timing result for merge1.c
Reading length = 23.055000
Allocating array = 0.000000
Reading array = 0.010000
Sorting array = 0.020000
Printing Sorted array = 0.000000
Freeing array = 0.000000
Timing result for merge2.c
Reading length = 22.763000
Allocating array = 0.000000
Reading array = 0.020000
Sorting array = 0.020000
Printing Sorted array = 0.000000
Freeing array = 0.000000

You can almost certainly beat scanf by writing your own little function to read numbers.
If all numbers are decimal and separated by something that isn't a digit, this would work:
char buffer[4096];
int bufcount;
int bufpos;
int get_next_char()
{
if (!bufcount)
{
bufcount = fread(buffer, 1, 4096, stdin);
bufpos = 0;
if (!bufcount){
return EOF;
}
}
bufcount--;
return buffer[bufpos++];
}
int is_digit(int ch)
{
if (ch >= '0' && ch <= '9')
return 1;
return 0;
}
int readnum()
{
int res = 0;
int ch;
do
{
ch = get_next_char();
} while(!is_digit(ch) && ch != EOF);
if (ch == EOF)
{
return 0xbaadbeef; // Don't expect this to happen.
}
do
{
res = (res * 10) + (ch - '0');
ch = get_next_char();
} while(is_digit(ch));
return res;
}
The code in scanf is a lot more complicated than this, and is highly likely to call getc or fgetc, which is a bit less efficient than the above code would be. However, it's worth measuring exactly where you are spending time. Print the time for each function as part of your output.

I would supplement Mats' answer by, rather than using stdin, having a file name as input.
Then open the file (in binary format if on Windows).
Get the file length, malloc a big-enough buffer, read the entire file into it, and close the file.
Then I would parse using a character pointer into the buffer.
That way, getting the next character doesn't require a function call.
That's hard to beat for speed.
The code for parsing an integer is:
num = 0;
while(isdigit(*pc)){
num = num*10 + (*pc++ - '0');
}

In optimization problem the rule of thumb is the best. Try to get numerics value of time spent in each step. Loading - sorting - etc... You can use a profiler for that (like gprof).
To faster your IO you should consider doing less call to scanf. As you have the number of scanf require you could design a better algorithm for this specific part.
Scanf do a lot of thing, parse the first arg, then read the byte and convert it to the format. If we want to go faster, we will use 'data problem' to skip some steps. First, we know that we are just using number define on N (math). Second, we know that every bytes are numbers or separators. We can use this.
So we use the read() system call that can read some byte from a file descriptor. The file descriptor for standard input change between operating system, but it is often 0.
The macro algorithm could be :
index = 0
buffer = new array[10000];
numberOfByteRead = 1
while there is byte that have been read at last call of read.
numberOfByteRead = read said 10000 byte to buffer;
parse the buffer
;;
parse(buffer,numberOfByteRead)
for all true byte in buffer :
switch (buffer[0])
case '0': { the mathematical operation on arr[index] that fit for '0'; break; }
case '1': { ... break;}
case ' ': {index++; break;}
;;
Not a really fun part to code, but faster than scanf.
Larger value that 10000, will reduce IO time, but increase memory.
You have to balance.

static char buff[8*1000000];
int i, length, blen;
int *ap, *p;
int n = 0;
char ch, *cp = buff;
scanf("%d%*c", &length);
p = ap = malloc(sizeof(*ap) * length);
blen = fread(buff, 1, 8*1000000, stdin);
while(blen--){
if(isdigit(ch=*cp++)){
n = n * 10 + ch - '0';
} else {
*p++ = n;
n = 0;
}
}

Related

C execution Time

I have a problem when I want to check my execution time with time.h in C. Namely; I added a timer for calculation of execution time when a search is started. However, the timer is starting when I select a number of variables.
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
int main()
{
int selection = 0;
printf(" 1. Calculate Execution Time Depends on Variables. \n 2. Calculate Variable Numbers Depends on Time Execution.\n What You want to do ? \n Selection : ");
scanf_s("%d", &selection);
if (selection==1)
{
int numberselection = 0;
int number_Elements = 0;
printf(" Please Select the Number of Elements. \n 1. 500.000 2. 1.000.000 3. 2.000.000 4. 3.000.000 5. 100.000.000 \n Selection : ");
scanf_s("%d", &numberselection);
if (numberselection==1)
{
number_Elements = 500000;
}
if (numberselection == 2)
{
number_Elements = 1000000;
}
if (numberselection == 3)
{
number_Elements = 2000000;
}
if (numberselection == 4)
{
number_Elements = 3000000;
}
if (numberselection == 5)
{
number_Elements = 100000000;
}
int i = 0;
int *NumberList = malloc(number_Elements * sizeof(int));
NumberList[number_Elements];
srand((unsigned)time(NULL));
for (i = 0; i < number_Elements; i++)
{
double random = rand() % 99999 + 99999999;
NumberList[i] = random;
}
double number_Search;
printf("\n Please Enter Number To Search : ");
scanf_s("%d", &number_Search);
Algorithm(number_Elements, NumberList, number_Search);
}
return 0;
}
int Algorithm(int G_Number_Elements , int G_NumberList[] , int G_Number_Search)
{
int k = 0;
double time_taken = 0;
clock_t t = 0;
for ( k = 0; k < G_Number_Elements; k++) // NUMBER TO TIME
{
if (G_NumberList[k] == G_Number_Search)
{
break;
}
else
{
printf("\n Not Found...");
break;
}
}
t = clock() - t;
time_taken = ((double)t) / CLOCKS_PER_SEC;
printf("\n Exacution Time Depends %d Variables = %f ms.\n", G_Number_Elements, time_taken);
return 0;
}
The time I wait for the console is added when I get the timer value. I have a two scenario;
Pictures of Scenarios
My question is that, How can I eliminate the waiting time from the timer?
I solved problem by the help of #Korrat !
Last state of codes :
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
int main()
{
int selection = 0;
printf(" 1. Calculate Execution Time Depends on Variables. \n 2. Calculate Variable Numbers Depends on Time Execution.\n \n What You Want to Do ? \n Selection : ");
scanf_s("%d", &selection);
if (selection == 1)
{
int numberselection = 0;
int number_Elements = 0;
printf(" Please Select the Number of Elements. \n 1. 500.000 2. 1.000.000 3. 2.000.000 4. 3.000.000 5. 100.000.000 \n Selection : ");
scanf_s("%d", &numberselection);
if (numberselection == 1)
{
number_Elements = 500000;
}
if (numberselection == 2)
{
number_Elements = 1000000;
}
if (numberselection == 3)
{
number_Elements = 2000000;
}
if (numberselection == 4)
{
number_Elements = 3000000;
}
if (numberselection == 5)
{
number_Elements = 100000000;
}
int i = 0;
int *NumberList = malloc(number_Elements * sizeof(int));
NumberList[number_Elements];
srand((unsigned)time(NULL));
for (i = 0; i < number_Elements; i++)
{
double random = rand() % 99999 + 99999999;
NumberList[i] = random;
}
double number_Search;
printf("\n Please Enter Number To Search : ");
scanf_s("%d", &number_Search);
int k = 0;
clock_t begin = clock();
for (k = 0; k <= number_Elements; k++) // NUMBER TO TIME
{
if (NumberList[k] == number_Search)
{
break;
}
if (k == number_Elements)
{
printf("Your Number Not Found in List ! \n");
}
}
clock_t end = clock();
float time_spent = (double)(end - begin) / CLOCKS_PER_SEC;
printf("\n Exacution Time Depends %d Variables = %f Second !. \n", number_Elements, time_spent);
}
return 0;
}
The problem is that clock() counts all clock ticks your program uses.
You probably want to initialize t to the current value of clock() like this
clock_t t = clock();
That way you take the amount of time spent on selecting your input out of the time calculation.
Additinal information taken from the C reference on clock()
To calculate the actual processing time of a program, the value returned by clock shall be compared to a value returned by a previous call to the same function.

how to change this code to be able to solve this challenge?

I'm new in programming and I'm trying to solve some problems from online websites. And one of this problems stopped me.
You can download problem here : https://uva.onlinejudge.org/external/101/10191.pdf
I don't know how to change this code in order to determine itself where to end reading data from console.
here is the code that I wrote :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_LINE 256
int second_time(char a[])
{
int hour1, minute1, time;
hour1 = a[6] - '0';
hour1 *= 10;
hour1 += a[7] - '0';
minute1 = a[9] - '0';
minute1 *= 10;
minute1 += a[10] - '0';
time = (60*hour1) + minute1;
return time;
}
int first_time(char b[])
{
int hour2, minute2, time;
hour2 = b[0] - '0';
hour2 *= 10;
hour2 += b[1] - '0';
minute2 = b[3] - '0';
minute2 *= 10;
minute2 += b[4] - '0';
time = (60*hour2) + minute2;
return time;
}
int main(void) {
char line[MAX_LINE];
int i, j, s, k;
int first, second, delta;
scanf("%i", &s);
getchar();
int max[4], max_hour[4];
int flag = 1;
for(k=0; k<4; k++)
{
max[k] = 0;
}
while(flag)
{
for(i=0;i<s-1; i++)
{
if(i%2 == 0)
{
scanf ("%[^\n]%*c", line);
second = second_time(line);
if(s%2 == 0)
{
i++;
}
}
scanf ("%[^\n]%*c", line);
first = first_time(line);
delta = first - second;
if (delta > max[k])
max_hour[k] = second;
max[k] = delta;
second = second_time(line);
}
}
for(k=0; k<4; k++)
{
if(delta < 60)
printf("Day #%i: the longest nap starts at %.2i:%.2i and will last for %i minutes.\n", k+1, max_hour[k]/60, max_hour[k]%60, max[k]);
else
printf("Day #%i: the longest nap starts at %.2i:%.2i and will last for %i hours and %i minutes.\n", k+1, max_hour[k]/60, max_hour[k]%60, max[k]/60, max[k]%60);
}
return 0;
}
I've got AC with the following code
Code:
#include <stdio.h>
int main()
{
int s, c, day = 0, z, cp, cb, m;
int f[480], beg, max;
int h1, m1, h2, m2;
int p1, p2;
char line[256];
while (scanf("%d\n", &s) != EOF) {
++day;
for (z = 0; z < 480; ++z) f[z] = 1;
beg = 0;
max = 0;
for (c = 0; c < s; ++c) {
scanf("%d:%d %d:%d", &h1, &m1, &h2, &m2);
fgets(line, 256, stdin);
p1 = (h1 - 10) * 60 + m1;
p2 = (h2 - 10) * 60 + m2;
for (cp = p1; cp < p2; ++cp) f[cp] = 0;
}
c = 0;
while (c < 480) {
if (f[c]) {
cb = c;
m = 0;
while (f[c] && c < 480) {
++c;
++m;
}
if (m > max) {
beg = cb;
max = m;
}
} else {
++c;
}
}
printf("Day #%d: the longest nap starts at %02d:%02d and will last for ", day, 10 + beg / 60, beg % 60);
if (max > 59) printf("%d hours and ", max / 60);
printf("%d minutes.\n", max % 60);
}
return 0;
}
The function scanf() returns the number of items successfully matched. Use this return value in order to set your infinite loop and check whether you've reached EOF. Moreover, for these problems, you should usually print the results instance by instance, you do not need to keep all the answers in a vector (you don't know how large it will be anyway).
You have assumed the schedules are given in sorted order. It is not. So you need to sort it and then just linearly check the maximum free gap.
When to stop reading data?
Just takes input like this
while(scanf("%d",&s)!=EOF)
{
read s schedule.
sort
get maximum free gap
****BINGO****
....
}
Note: sorting is not relevant to looping but to your AC solution it is.
Code
struct schedule
{
int start;
int end;
}
struct schedule ss[MAX+1];
while(scanf("%d",&s)!=EOF)----> This is when you know you have to stop when it return EOF
{
First element of ss I would set as ss[0]={6000,6000}
last element of ss I would set as ss[s]={1080,1080}
Get s schedules and put them in ss
sort them
for each of the elements starting from 1 to s
get max ( ss[i].start - ss[i-1].end)
and corresponding end time.
get maximum free gap
****BINGO****
....
}
As you insisted your code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_LINE 256
int second_time(char a[])
{
int hour1, minute1, time;
hour1 = a[6] - '0';
hour1 *= 10;
hour1 += a[7] - '0';
minute1 = a[9] - '0';
minute1 *= 10;
minute1 += a[10] - '0';
time = (60*hour1) + minute1;
return time;
}
int first_time(char b[])
{
int hour2, minute2, time;
hour2 = b[0] - '0';
hour2 *= 10;
hour2 += b[1] - '0';
minute2 = b[3] - '0';
minute2 *= 10;
minute2 += b[4] - '0';
time = (60*hour2) + minute2;
return time;
}
int main(void) {
char line[MAX_LINE];
int i, j, s, k;
int first, second, delta;
int max[200], max_hour[200];
int flag = 1;
for(k=0; k<200; k++)
{
max[k] = 0;
}
while(scanf("%i", &s)!=EOF)
{
getchar();
for(i=0;i<s-1; i++)
{
if(i%2 == 0)
{
scanf ("%[^\n]%*c", line);
second = second_time(line);
if(s%2 == 0)
{
i++;
}
}
scanf ("%[^\n]%*c", line);
first = first_time(line);
delta = first - second;
if (delta > max[k])
max_hour[k] = second;
max[k] = delta;
second = second_time(line);
}
for(k=0; k<s; k++)
{
if(delta < 60)
printf("Day #%i: the longest nap starts at %.2i:%.2i and will last for %i minutes.\n", k+1, max_hour[k]/60, max_hour[k]%60, max[k]);
else
printf("Day #%i: the longest nap starts at %.2i:%.2i and will last for %i hours and %i minutes.\n", k+1, max_hour[k]/60, max_hour[k]%60, max[k]/60, max[k]%60);
}
}
return 0;
}
Correct solution
typedef struct {
int st, ed;
} schedule;
int cmp(const void *i, const void *j) {
schedule *a, *b;
a = (schedule *)i, b = (schedule *)j;
return a->st <= b->st;
}
int main() {
int n, i, a, b, c, d, day = 0;
schedule TT[100];
while(scanf("%d", &n) !=EOF) {
for(i = 0; i < n; i++) {
scanf("%d:%d %d:%d", &a, &b, &c, &d);
getchar();
TT[i].st = a*60 + b;
TT[i].ed = c*60 + d;
}
qsort(TT, n, sizeof(schedule), cmp);
int beg = 600, ans = 0, point;
for(i = 0; i < n; i++) {
if(( TT[i].st-beg ) > ans)
ans = (TT[i].st-beg ), point = beg;
beg = TT[i].ed;
}
if((1080 - beg) > ans)
ans = (1080- beg), point = beg;
printf("Day #%d: the longest nap starts at ", ++day);
printf("%02d:%02d and will last for ", point/60, point%60);
if(ans >= 60)
printf("%d hours and ", ans/60);
printf("%d minutes.\n", ans%60);
}
return 0;
}

Why my program gets a segfault in linux-gcc but not on mingw-gcc?

I have written a program in C. The problem is when I compile this program in a Linux/Unix environment I get a segfault. But when I compile it in Windows with minGW It works fine. Basically in the program I have a multidimensional array. When I compile and debug in gdb in Linux/Unix I lose one row of the multidimensional array randomly. When I try to access every column in that row all of them suddenly cannot be accessed. My whole row gets lost.
Error:Program received signal SIGSEGV, Segmentation fault.
Note: isItDone(), oneToTwo(), and checkAroundTwo() are very likely not the problem. I tried running program without them and it still showed the error.
The code:
int main( int argc, char *argv[] ){
FILE * output;
output = fopen("output.txt", "w");
srand(time(NULL));
int size = 0; // Resetting before taking arguments
int evaltime = 0; // Resetting before taking arguments
int rand1, rand2;
int counter, counter2, counter3;
if(argc == 3){
size = atoi(argv[1]);
evaltime = atoi(argv[2]);
}
else{
return 0;
}
double *evaltimes = (double*)calloc(evaltime , sizeof(double)); // The array of the results we got.
for(counter2 = 0; counter2 < evaltime; counter2++){
int cellnumbers = 0;
int **ground = (int**)malloc(size * sizeof(int)); //Mallocating for every iteration
for(counter = 0; counter < size; counter++){
ground[counter] = (int*)calloc(size, sizeof(int)); // Initializing all the 0.
}
while(!isItDone(ground, size)){ // It's finished when last row is 2.
rand1 = rand() % size;
rand2 = rand() % size; // Take two random numbers for picking in array limit.
printf("%d %d\n", rand1, rand2);
if(rand1 == 0){ // Is it a top cell
if(ground[rand1][rand2] == 0){
ground[rand1][rand2] = 2;
cellnumbers++; // Increment when a cell is picked.
}
}
else{
if(ground[rand1][rand2] == 1 || ground[rand1][rand2] == 2) // The cell is already opened
continue;
else{
ground[rand1][rand2] = 1; // Defaulting to 1 before control
cellnumbers++;
oneTotwo(ground, size, rand1, rand2);
}
}
}
if(counter2 == evaltime - 1){ // Printing the last variation
for(counter3 = 0; counter3 < size; counter3++){
for(counter = 0; counter < size; counter++){
fprintf(output, "%d ",ground[counter3][counter]);
}
fprintf(output, "\n");
}
}
evaltimes[counter2] = (double)cellnumbers / (double)(size*size);
for(counter = 0; counter < size; counter++)
free(ground[counter]);
free(ground);
}
double meany = mean(evaltimes, evaltime);
double stddeviation = stddev(evaltimes, evaltime, meany);
fprintf(output, "mean() = %f \n", meany);
fprintf(output, "stddev() = %f",stddeviation);
fclose(output);
return 0;
}
I think the bug is most likely lies in main but here are my functions.
int isItDone(int **p, int size){
int counter;
for(counter = 0; counter < size; counter++){
if(p[size - 1][counter] == 2 && (p + size - 1) != 0)
return 1;
}
return 0;
}
void oneTotwo(int **p, int size, int rand1, int rand2){
//Checking the Upper Cells
if(rand1 < size - 1){ // Making sure no control if it is the last cell.
if(p[rand1 + 1][rand2] == 2){
p[rand1][rand2] = 2;
checkAroundTwo(p, size, rand1, rand2);
}
}
if(rand1 > 0){
if(p[rand1 - 1][rand2] == 2){
p[rand1][rand2] = 2;
checkAroundTwo(p, size, rand1, rand2);
}
}
if(rand2 < size - 1){
if(p[rand1][rand2 + 1] == 2){
p[rand1][rand2] = 2;
checkAroundTwo(p, size, rand1, rand2);
}
}
if(rand2 > 0){
if(p[rand1][rand2 - 1] == 2){
p[rand1][rand2] = 2;
checkAroundTwo(p, size, rand1, rand2);
}
}
}
void checkAroundTwo(int **p, int size, int rand1, int rand2){
if(rand1 < size - 1){
if(p[rand1 + 1][rand2] == 1){
p[rand1 + 1][rand2] = 2;
checkAroundTwo(p, size, rand1 + 1, rand2);
}
}
if(rand1 > 0){
if(p[rand1 - 1][rand2] == 1){
p[rand1 - 1][rand2] = 2;
checkAroundTwo(p, size, rand1 - 1, rand2);
}
}
if(rand2 < size - 1){
if(p[rand1][rand2 + 1] == 1){
p[rand1][rand2 + 1] = 2;
checkAroundTwo(p, size, rand1, rand2 + 1);
}
}
if(rand2 > 0){
if(p[rand1][rand2 - 1] == 1){
p[rand1][rand2 - 1] = 2;
checkAroundTwo(p, size, rand1, rand2 - 1);
}
}
}
double mean(double *p, int size){
double sum = 0.0000000;
int counter;
for(counter = 0; counter < size; counter++)
sum += p[counter];
return sum / (double)(size);
}
double stddev(double *p, int size, double mean){
double sum = 0.0000000;
int counter;
for(counter = 0; counter < size; counter++)
sum += sqr(((double)p[counter] - mean));
return sqrt(sum / (double)(size - 1));
}
double sqr(double x){
return x*x;
}
double sqrt(double x){
int counter = 0;
while(sqr(counter) < x){
counter++;
}
double s = counter;
for(counter = 0; counter < 50; counter++){
s = (double)1/2 * (double)(s + x/s);
}
return s;
}
Let's assume int array[10][10]
One more weird thing is that in gdb when I for example lose array[5] row I try to access it from the row before it. For example with array[4][10]. When I do it "array[4][10] = 49". Why is this? Rest is (array[4][12], array[4][13] etc.) is 0 as I specified. Why suddenly the first element of the 5th row achieved from the 4th row becomes 49 ? That I dont understand.
When you assign memory to a 2D array, you're assigning an array of pointers, each of which points to a block of memory.
This means when you do your initial malloc you need to assign ...sizeof(int*) and not ...sizeof(int).
In short, change this line:
int **ground = (int**)malloc(size * sizeof(int));
to:
int **ground = (int**)malloc(size * sizeof(int*));

Not reading anything past scanf()

I am new to C and wondering why I am not getting any kind of output. I am trying to get my program to convert a hexadecimal number to binary.
#include <stdio.h>
#include <stdlib.h>
int* hex2binary(int hex_array[], int input_array_size, int* return_array_size) {
int hex_size = input_array_size;
int binary_array_size = 4 * hex_size;
int *binary_array = (int*) malloc(binary_array_size * sizeof(int));
int hex_index, binary_index;
for (hex_index = 0; hex_index < hex_size; hex_index++) {
int hex_num = hex_array[hex_index];
binary_index = hex_index * 4;
int bit_count;
for (bit_count = 3; bit_count <= 0; bit_count--) {
binary_array[binary_index + bit_count] = hex_num % 2;
hex_num = hex_num / 2;
}
hex_index++;
}
*return_array_size = binary_array_size;
return binary_array;
}
int main() {
char baseString[11];
int count = 0;
int i, j;
int original, wanted;
int size;
printf("Welcome to use this number base converter program.\n");
printf("Please input the original base: ");
scanf("%d", &original);
printf("Please input a base-%d number with more more than 10 digits: ",
original);
scanf("%s", baseString);
while (baseString[count] != '\0')
count++;
int *baseNumber = (int*) malloc(count * sizeof(int));
for (i = 0; i < count; i++) {
baseNumber[i] =
baseString[i] <= '9' ? baseString[i] - '0' : baseString[i] - 'A' + 10;
}
int* result_array;
printf("Please input the target base: ");
scanf("%d", &wanted); //doesn't read anything past this point
printf("Target base: %d", wanted);
if (original == 16) {
if (wanted == 2) {
result_array = hex2binary(baseNumber, count, size);
for (j = 0; j < size; j++) {
printf("Result: %d", result_array[j]);
}
}
}
}
I know it can't be something to difficult, but I can't seem to figure out why it isn't even producing some kind of output.
This line
result_array = hex2binary(baseNumber, count, size);
is incorrect because this function needs a pointer argument
int* hex2binary(int hex_array[], int input_array_size, int* return_array_size)
So it should be called like this
result_array = hex2binary(baseNumber, count, &size); // note the &
Then the subsequent loop
for (j = 0; j < size; j++)
will no longer be using the uninitialised variable size.

c openmp - parallelization of a while loop

I would like to parallelize a while loop in C with OpenMP. It is a classic while until flag = false.
This is a semi-pseudo-code of my work without openMP
//Something before
found = 0;
while (!found){
//Pull an element from an array and do some work with it
if(something) found = 1;
//Do other work and put an element in the same array
}
//Something later
It is not a problem for me if the work in the loop is done some times more, it's just overwork that doesn't affect the results. There is a simple correct way to parallelize this with OpenMP in C?
Thanks
As requested, this is the complete code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <omp.h>
typedef struct location {int x, y;} location;
typedef struct node {
int x, y; // Coordinates of the node on the grid
int x_prec, y_prec; // Coordinates of the predecessor
int walkable; // Whether this node can be walked through
int opened; // It indicates if the node was been estimated
int closed; // It indicates if the node was been evaluated
int inPath; // If the node is in the shortest path
int g; /* The past-cost function, which is the known distance from the starting
* node to the current one. */
int f; /* The estimated-cost function, which is an admissible heuristic estimate
* of the distance from the starting node to the goal passing through the
* current node. */
int h; // The estimated cost of the path between the current node and the goal
} node;
typedef struct list {
location loc;
int isValid;
} list;
location start,end;
node **grid;
int cols, rows;
double time1, time2, time3, time4, time5;
double time_aStar_s, time_aStar_e;
double time_getNeighbor_s, time_getNeighbor_e;
double time_while_s, time_while_e;
double time_for_s, time_for_e;
double time_for = 0;
double time_pull_s, time_pull_e;
double time_pull = 0;
int count_getNeighbor = 0;
int count_current = 0;
void setGrid(char [6]);
int checkLocation(location);
void aStar(int);
int isListEmpty(list *);
void constructPath(location);
void getNeighbor(location, location *);
int heuristic(location, location);
void printStatistics();
void saveStatistics(char *);
int main (int argc, char *argv[]){
char input_map[20];
int input_algo = -1;
char input_stat[20];
printf("Which map you prefer?\n");
scanf("%s", input_map);
setGrid(input_map);
printf("Enter a valid start point.\n");
scanf("%i", &start.x);
scanf("%i", &start.y);
printf("Enter a valid end point.\n");
scanf("%i", &end.x);
scanf("%i", &end.y);
if (checkLocation(start) || checkLocation(end)) printf("Invalid start and/or end points.\n");
printf("Dijkstra or A*?(press <0> or <1> respectively)\n");
scanf("%i", &input_algo);
// Save when aStar is called
time_aStar_s = omp_get_wtime();
if(input_algo == 0) aStar(0); // 0 for Dijkstra
else if (input_algo == 1) aStar(1); // 1 for A*
// Save when aStar finishes
time_aStar_e = omp_get_wtime();
printf("End of the program. \n");
printStatistics();
printf("Would you like to save the statistics?(Enter <y> or <n> respectively)\n");
scanf("%s", input_stat);
if(input_stat[0] == 'y'){
printf("Enter file name.\n");
scanf("%s", input_stat);
saveStatistics(input_stat);
}
return(0);
}
void setGrid(char mapName[6]) {
char temp[1024];
char fileName[20];
int i,j;
FILE *file;
// Try to open the file
strcpy(fileName, "src/maps/");
strcat(fileName, mapName);
if((file = fopen(fileName, "r")) == NULL){
printf("ERROR: No such file.\n");
exit(1);
}
// Save dimensions of the map
rows = 0;
while(42){
if(fscanf(file, "%s", temp) == EOF){
printf("EOF\n");
printf("columns: \t%i \nrows: \t\t%i\n", cols, rows);
break;
}
printf("%s\n", temp);
cols = strlen(temp);
rows++;
}
// Reset the file position indicator
rewind(file);
// Set dimensions of grid matrix
grid = (node **)malloc(rows * sizeof(node*));
for(i = 0; i < rows; i++) grid[i] = (node *)malloc(cols * sizeof(node));
i=0;
while(42){
if(fscanf(file, "%s", temp) == EOF) break;
for (j = 0; j < cols; j++) {
grid[i][j].x = i;
grid[i][j].y = j;
grid[i][j].x_prec = -1;
grid[i][j].y_prec = -1;
if(temp[j] == '#') {
grid[i][j].walkable = 0;
} else if(temp[j] == '-') {
grid[i][j].walkable = 1;
}
grid[i][j].opened = 0;
grid[i][j].closed = 0;
grid[i][j].inPath = 0;
grid[i][j].g = -1;
grid[i][j].f = -1;
}
i++;
}
fclose(file);
}
void printGrid(int option) {
int i,j;
switch(option){
case 0:
// It prints grid with start point, end point and optimal path
for(i = 0; i < rows; i++) {
for(j = 0; j < cols; j++) {
if(i == start.x && j == start.y) printf("S");
else if(i == end.x && j == end.y) printf("E");
else if (grid[i][j].walkable){
if (grid[i][j].inPath) printf("+");
else printf(" ");
} else printf("#");
}
printf("\n");
}
printf("\n");
break;
case 1:
// It prints evaluated cost g
for(i = 0; i < rows; i++) {
for(j = 0; j < cols; j++) {
if (grid[i][j].walkable){
if(grid[i][j].closed == 1) printf("%3d ", grid[i][j].g);
else printf(" ");
} else printf("### ");
}
printf("\n");
}
printf("\n");
break;
case 2:
// It prints estimated cost g
for(i = 0; i < rows; i++) {
for(j = 0; j < cols; j++) {
if (grid[i][j].walkable){
if(grid[i][j].closed == 1) printf("%3d ", grid[i][j].g);
else printf(" ");
} else printf("### ");
}
printf("\n");
}
printf("\n");
break;
default:
printf("ERROR: Bad option %i for function printGrid(). Please check the code.\n", option);
break;
}
}
int checkLocation(location l) {
if(grid[l.x][l.y].walkable) return(0);
else return (1);
}
void aStar(int opt_dijkstra) {
list openList[10000];
location current;
location neighbors[4];
int empty;
int found = 0;
int i,j; // Counters
int exit; // control variable
int f_min;
int pos;
int x,y;
int ng;
// Set g and f values of the start node to be 0
grid[start.x][start.y].g = 0;
grid[start.x][start.y].f = 0;
// Initialization of the open list
for (i = 0; i < sizeof(openList)/sizeof(openList[0]); i++) {
openList[i].isValid = 0;
}
// Push the start node into the open list
grid[start.x][start.y].opened = 1;
openList[0].loc.x = start.x;
openList[0].loc.y = start.y;
openList[0].isValid = 1;
// Save when the "while is not empty" begins
time1 = time_while_s = omp_get_wtime();
// While the open list is not empty
empty = isListEmpty(openList);
while (!empty && !found){
// Save time to pull a node
time_pull_s = omp_get_wtime();
// pull the position of the node which has the minimum f value
f_min = -1;
#pragma omp parallel for default(none) shared(openList, f_min, current, pos, grid)
for(i = 0; i < sizeof(openList)/sizeof(openList[0]); i++) {
if (openList[i].isValid == 1 && (f_min == -1 || (grid[openList[i].loc.x][openList[i].loc.y].f < f_min))){
#pragma omp critical(pullopenlist)
{
f_min = grid[openList[i].loc.x][openList[i].loc.y].f;
current.x = openList[i].loc.x;
current.y = openList[i].loc.y;
pos = i;
}
}
}
openList[pos].isValid = 0;
grid[current.x][current.y].closed = 1;
//Save time to pull a node
time_pull_e = omp_get_wtime();
time_pull += time_pull_e - time_pull_s;
// Update the count of evaluated points
count_current++;
// If the end position is reached, construct the path and return it
if (current.x == end.x && current.y == end.y){
printf("Reached the end position.\n");
constructPath(end); // To be defined
found = 1;
}
// Save when enter in getNeighbor
time_getNeighbor_s = omp_get_wtime();
// Get neighbors
getNeighbor(current, neighbors);
// Save when exit from getNeigbor
time_getNeighbor_e = omp_get_wtime();
// Get the distance between current node and the neighbor and calculate the next g score
ng = grid[current.x][current.y].g + 1;
// Save when started the "for all neighbors"
time2 = time_for_s = omp_get_wtime();
// Evaluate neighbors
/* Seems that is not convenient to parallelize the loop.
* Probably this happens because of critical section
*/
#pragma omp parallel for default(none) private(x, y, j) shared(exit, openList, neighbors, ng, grid, opt_dijkstra, end, current)
for (i = 0; i < 4; i++) {
x = neighbors[i].x;
y = neighbors[i].y;
if (x != -1 || y != -1){
// Check if the neighbor has not been inspected yet, or if it
// can be reached with smaller cost from the current node
if (!grid[x][y].opened || ng < grid[x][y].g) {
grid[x][y].g = ng;
if(opt_dijkstra == 0) grid[x][y].h = 0; // Dijkstra case with heuristic cost = 0;
else grid[x][y].h = heuristic(neighbors[i], end);
grid[x][y].f = grid[x][y].g + grid[x][y].h;
grid[x][y].x_prec = current.x;
grid[x][y].y_prec = current.y;
}
// If the neighbor is not in open list push it into it
#pragma omp critical (pushopenList)
{
if(!grid[x][y].opened) {
exit = 0;
for(j = 0; exit == 0; j++) {
if(openList[j].isValid == 0) {
openList[j].loc.x = x;
openList[j].loc.y = y;
openList[j].isValid = 1;
exit = 1;
}
}
}
grid[x][y].opened = 1;
}
}
}
// Save when finish the "for all neighbors"
time_for_e = omp_get_wtime();
time_for += time_for_e - time_for_s;
} // End while the open list is not empty until end point is found.
// Save when finish the "while is not empty"
time_while_e = omp_get_wtime();
}
int isListEmpty(list l[]){
// It should check if the list is empty. It checks if there is at least one element that is valid.
int i;
int empty = 0;
for (i = 0; i < sizeof(l)/sizeof(l[0]); i++){
if (l[i].isValid){
empty = 1;
i = sizeof(l)/sizeof(l[0]);
}
}
return (empty);
}
void constructPath(location n){
/* The function reconstructs the path starting from the given point setting .inPath
*/
int i;
location temp;
location temp_prec;
temp.x = grid[n.x][n.y].x;
temp.y = grid[n.x][n.y].y;
grid[temp.x][temp.y].inPath = 1;
for(i = 0; grid[temp.x][temp.y].x_prec != -1; i++) {
temp_prec.x = grid[temp.x][temp.y].x_prec;
temp_prec.y = grid[temp.x][temp.y].y_prec;
temp.x = temp_prec.x;
temp.y = temp_prec.y;
grid[temp.x][temp.y].inPath = 1;
}
}
void getNeighbor(location current, location neighbors[4]){
/*
* Get the neighbors of the given node.
*
* offsets
* +---+---+---+
* | | 0 | |
* +---+---+---+
* | 3 | | 1 |
* +---+---+---+
* | | 2 | |
* +---+---+---+
*/
int i;
int x = current.x;
int y = current.y;
// Update count of getNeighbor executions
count_getNeighbor++;
for (i = 0; i < 4; i++){
switch(i) {
// ↑
case 0:
if(x >= 0 && y - 1 >= 0 && x < rows && y - 1 < cols && grid[x][y - 1].walkable){
neighbors[i].x = x;
neighbors[i].y = y - 1;
} else{
neighbors[i].x = -1;
neighbors[i].y = -1;
}
break;
// →
case 1:
if(x + 1 >= 0 && y >= 0 && x + 1 < rows && y < cols && grid[x +1][y].walkable){
neighbors[i].x = x + 1;
neighbors[i].y = y;
} else{
neighbors[i].x = -1;
neighbors[i].y = -1;
}
break;
// ↓
case 2:
if(x >= 0 && y + 1 >= 0 && x < rows && y + 1 < cols && grid[x][y + 1].walkable) {
neighbors[i].x = x;
neighbors[i].y = y + 1;
} else{
neighbors[i].x = -1;
neighbors[i].y = -1;
} break;
// ←
case 3:
if(x - 1 >= 0 && y >= 0 && x - 1 < rows && y < cols && grid[x - 1][y].walkable) {
neighbors[i].x = x - 1;
neighbors[i].y = y;
} else{
neighbors[i].x = -1;
neighbors[i].y = -1;
}
break;
}
}
}
int heuristic(location from, location to){
int h;
// Manhattan distance from the two points
h = abs(from.x - to.x) + abs(from.y - to.y);
return(h);
}
void printStatistics(){
// Print some useful statistics about the parallel execution of the program
printf("\nStatistics of aStar:\n");
printf("time to execute aStar: \t\t\t\t%f \tms\n", 1000*(time_aStar_e - time_aStar_s));
printf("time at first check point: \t\t\t%f \tms\n", 1000*(time1 - time_aStar_s));
printf("time at second check point: \t\t\t%f \tms\n", 1000*(time2 - time_aStar_s));
printf("\nStatistic of \"while until is empty\":\n");
printf("number of iterations: \t\t\t\t%i\n", count_current);
printf("mean time to do an iteration: \t\t\t%f \tms\n", 1000*(time_while_e - time_while_s)/count_current);
printf("time to do all iterations: \t\t\t%f \tms\n", 1000*(time_while_e - time_while_s));
printf("\nStatistic of pull a node into openList:\n");
printf("mean time to perform a pull operation: \t\t%f \tms\n", 1000*time_pull/count_current);
printf("total time spent to perform pulls operations: \t%f \tms\n", 1000*time_pull);
printf("\nStatistic of \"for each neighbor\":\n");
printf("total number of iterations: \t\t\t%i\n", 4*count_current);
printf("mean time to do all four iterations: \t\t%f \tms\n", 1000*time_for/count_current);
printf("time to do the last four iterations: \t\t%f \tms\n", 1000*(time_for_e - time_for_s));
printf("time to do all the iterations: \t\t\t%f \tms\n", 1000*time_for);
printf("\nStatistic of getNeighbor:\n");
// time_getNeighbor is updated at each execution, so we have only the value relative to the last execution
printf("time to execute getNeighbor (last execution): \t%f \tms\n", 1000*(time_getNeighbor_e - time_getNeighbor_s));
printf("number of executions: \t\t\t\t%i\n", count_getNeighbor);
// Just an indicative time, it is NOT the time to do all executions
printf("estimated time to do all executions: \t\t%f \tms\n", 1000*count_getNeighbor*(time_getNeighbor_e - time_getNeighbor_s));
}
void saveStatistics(char *string_input){
FILE *fileOutput;
char fileOutputName[30];
strcpy(fileOutputName, "src/stats/");
strcat(fileOutputName, string_input);
if((fileOutput = fopen(fileOutputName, "w")) == NULL){
printf("ERROR: Error in opening the output file.\n");
exit(1);
}
// Print some useful statistics about the parallel execution of the program
fprintf(fileOutput, "\nStatistics of aStar:\n");
fprintf(fileOutput, "time to execute aStar: \t\t\t\t%f \tms\n", 1000*(time_aStar_e - time_aStar_s));
fprintf(fileOutput, "time at first check point: \t\t\t%f \tms\n", 1000*(time1 - time_aStar_s));
fprintf(fileOutput, "time at second check point: \t\t\t%f \tms\n", 1000*(time2 - time_aStar_s));
fprintf(fileOutput, "\nStatistic of \"while until is empty\":\n");
fprintf(fileOutput, "number of iterations: \t\t\t\t%i\n", count_current);
fprintf(fileOutput, "mean time to do an iteration: \t\t\t%f \tms\n", 1000*(time_while_e - time_while_s)/count_current);
fprintf(fileOutput, "time to do all iterations: \t\t\t%f \tms\n", 1000*(time_while_e - time_while_s));
fprintf(fileOutput, "\nStatistic of pull a node into openList:\n");
fprintf(fileOutput, "mean time to perform a pull operation: \t\t%f \tms\n", 1000*time_pull/count_current);
fprintf(fileOutput, "total time spent to perform pulls operations: \t%f \tms\n", 1000*time_pull);
fprintf(fileOutput, "\nStatistic of \"for each neighbor\":\n");
fprintf(fileOutput, "total number of iterations: \t\t\t%i\n", 4*count_current);
fprintf(fileOutput, "mean time to do all four iterations: \t\t%f \tms\n", 1000*time_for/count_current);
fprintf(fileOutput, "time to do the last four iterations: \t\t%f \tms\n", 1000*(time_for_e - time_for_s));
fprintf(fileOutput, "time to do all the iterations: \t\t\t%f \tms\n", 1000*time_for);
fprintf(fileOutput, "\nStatistic of getNeighbor:\n");
// time_getNeighbor is updated at each execution, so we have only the value relative to the last execution
fprintf(fileOutput, "time to execute getNeighbor (last execution): \t%f \tms\n", 1000*(time_getNeighbor_e - time_getNeighbor_s));
fprintf(fileOutput, "number of executions: \t\t\t\t%i\n", count_getNeighbor);
// Just an indicative time, it is NOT the time to do all executions
fprintf(fileOutput, "estimated time to do all executions: \t\t%f \tms\n", 1000*count_getNeighbor*(time_getNeighbor_e - time_getNeighbor_s));
fclose(fileOutput);
printf("Saved all the stats");
}
If you have suggestion on the other parts of code you're welcome.
You can certainly do something like this with OpenMP, but it isn't as simple as putting #pragma omp parallel around a for loop. For that structure, the compiler needs to know at the time of entering the loop how many iterations will be made, so that it can decompose the iterations across threads; and you necessarily don't have that information here when you're exiting once you've found something.
You can make something like this work - and it can be very useful if the test you need to perform is very CPU heavy (here, I have a made-up example of brute-force primality testing), so that you're breaking up the work amongst several cores, and you only care about finding a result (or that there are none). But note that you are definitely not guaranteed that doing this in parallel will return the first result.
In the below example, we have a flag found that is set (using an omp atomic capture construct) when a thread finds an item. If it was the first to set the flag, it stores the value and location. Once the threads (eventually) see the flag has been set, they all return from the while loop.
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include "omp.h"
/* brute force prime-testing algorithm */
int isprime(int x) {
int prime = 1;
for (int i=2; i<=floor(sqrt(1.0*x)); i++) {
if (x % i == 0) {
prime = 0;
break;
}
}
return prime;
}
int main(int argc, char **argv) {
const int MAXN=128;
int start=200;
if (argc > 1)
start = atoi(argv[1]);
int candidates[MAXN];
for (int i=0; i<MAXN; i++) {
candidates[i] = start+i;
}
int found=0;
int value=-1;
int location=-1;
#pragma omp parallel shared(found, candidates, value, location) default(none)
{
int tid=omp_get_thread_num();
int nthreads=omp_get_num_threads();
int item=tid;
while (!found && item < MAXN) {
int prime=isprime(candidates[item]);
if (prime) {
int alreadyfound=0;
#pragma omp atomic capture
{ alreadyfound = found; found++; }
if (!alreadyfound) {
location = item;
value = candidates[item];
}
}
item += nthreads;
}
}
if (!found)
printf("No primes found\n");
else
printf("Found prime: %d (%d) in location %d (%d)\n", value, isprime(value), location, candidates[location]);
return 0;
}
Running gives
$ gcc -o stopwhenfound stopwhenfound.c -std=c99 -lm -fopenmp
$ ./stopwhenfound 370262
Found prime: 370373 (1) in location 111 (370373)
I disagree with Jonathan, I think it is very easy to do in OpenMP. You just need to flush the done variable (so its value is consistent across all the caches):
//Something before
found = 0;
**#pragma omp flush(done)**
while (!found){
//Pull an element from an array and do some work with it
if(something){
found = 1;
**#pragma omp flush(done)**
}
//Do other work and put an element in the same array
}
//Something later

Resources