This is a program made in C that compiles fine using gcc filename.c -o file -pthread. However when I go to run the program is tells me there is a segmentation fault and I am not sure how to fix it. This program is meant to make random integers in an array then compare how long it takes to find the 10 largest and 10 lowest numbers using a different amount of threads for reach iteration of the program.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <time.h>
#define arraySize 10000
#define lval 0
#define hval 50000
#define maxthread 100
int num[arraySize];
int maxs[maxthread];
int mins[maxthread];
int threadsize;
int threadnum = 0;
void fill(){
int i;
int tmp[hval];
for(i = lval;i < hval;i++)tmp[i] = i;
for(i = 0;i < arraySize;i++){
int t= i + rand()%(hval - 1);
int temp = tmp[i];
tmp[i] = tmp[t];
tmp[t] = temp;
num[i] = tmp[i];
}
}
void print(){
int i;
printf("First 10 Numbers are: \n");
for(i = 0;i < 10;i++)printf("\t%d\n",num[i]);
printf("\n\nLast 10 Numbers: \n");
for(i = (arraySize - 10);i < arraySize;i++)printf("\t%d\n",num[i]);
}
void *getminmax(void *arg){
int i,n = threadnum++;
int max = lval,min = hval;
for(i = n*(arraySize / threadsize);i < (n + 1)*(arraySize / threadsize);i++){
if (num[i] > max)max = num[i];
if (num[i] < min)min = num[i];
}
maxs[n] = max;
mins[n] = min;
printf("Threads:%d Min: %d Max%d Thread Num: %d\n",threadsize,min,max,n);
}
void search(){
int max = lval, min = hval;
int i;
int start = clock();
pthread_t threads[threadsize];
for(i = 0;i < threadsize;i++)
pthread_create(&threads[i],NULL,getminmax,(void*)NULL);
for(i = 0;i < threadsize;i++)
pthread_join(threads[i],NULL);
for(i = 0;i < threadsize;i++){
if(maxs[i] > max)max = maxs[i];
if(mins[i] < min)min = mins[i];
}
int end = clock();
int d = end - start;
printf("Threads %d Min: %d Time Taken: %d \n\n",threadsize,min,max,d);
}
int main(){
fill();
print();
threadsize = 2;
threadnum = 0;
search();
threadsize = 10;
threadnum = 0;
search();
threadsize = 100;
threadnum = 0;
search();
return 0;
}
There are few obvious bugs in your program.
As yano pointed out, t = i + rand()%(hval - 1); will produce a t in the range between 0 and arraySize + hval - 2. That later value is well outside the valid range for accessing tmp[t] and is likely the cause of the segmentation fault.
You probably meant this instead: t = (i + rand()) % (hval - 1);
The construct below is a data race. You are not at all guaranteeing distinct ns for different threads.
int n = threadnum++;
The usual fix for problem 2 is to pass the thread number as the arg (which you didn't use).
Related
So from the numbers from 1 to n, I have to compute how much the '1' digit occurs. For example: if n is 11, the total numbers is 4 (1, 10, 11). My assignment is saying that i have to use threads for this. This is what I've wrote so far:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
typedef struct {
int from;
int to;
} th_struct;
void *thread_function(void *param){
th_struct *st = (th_struct *) param;
int count = 0;
int nr;
for(int i = st->from; i <= st->to; i++){
nr = i + 1;
while(nr != 0 ){
if (nr % 10 == 1)
count++;
nr /= 10;
}
}
return (void *) (long) count;
}
int main(int argc, char **argv)
{
int threads, n, count = 0, result;
sscanf(argv[1], "%d", &n);
sscanf(argv[2], "%d", &threads);
th_struct info[threads];
pthread_t tid[threads];
for(int i = 0; i < threads; i++){
if(i == 0)
info[0].from = 0;
else
info[i].from = info[i - 1].to + 1;
info[i].to = info[i].from + n / threads - 1;
if(i < n / threads)
info[i].to++;
pthread_create(&tid[i], NULL, thread_function, &info[i]);
}
for(int i = 0; i < threads; i++){
pthread_join(tid[i], (void**)&result);
count += (int) (long) result;
}
printf("%d\n", count);
}
First command line argument is n, and the second is the number of threads. For n equal to 11, the output should be 4. But if I plug in 11 1 (n=11, nr of threads=1) the output is 5 (instead of 4). If i plug in 11 2 (two threads), the output is 9. The output should be the same, no matter how many threads I have.
I have tested the following code, and it works. It computes the number of '1' correctly (the following is the same as in the funcion "thread_function_ above", just adapted for testing):
int function(int n){
int count = 0;
int nr;
for(int i = 0; i <= n; i++){
nr = i + 1;
while(nr != 0 ){
if (nr % 10 == 1)
count++;
nr /= 10;
}
}
return count;
}
So the problem is thread related (I guess). Since this is my first program with threads, I don't know what the problem is. Thanks!
You have a few problems:
Incorrect input ranges:
info[0].from = 0;
...
if(i < n / threads)
info[i].to++;
Should be:
info[i].from = 1;
...
if (n % 2 == 1 && i + 1 == threads)
info[i].to++;
Invalid range processing:
nr = i + 1;
Should be:
nr = i;
Invalid result receiving.i changes its value while iterating for joining threads and for loop executes more times than intended:
pthread_join(tid[i], (void**)&result);
Should be:
void* result;
pthread_join(tid[i], &result);
Goldbach's conjecture states that every even integer over 4 is the sum of two primes, I am writing a program in C to find these pairs. To do this it first finds all the primes less than a user given number. I have a for loop to iterate from 4 to the user given number and find the pairs within the loop body. When that loop gets to about around 40, suddenly jumps back down by about 30 and then continues to iterate up (with user input 50 it jumped from 38 to 9, with input 60 it jumped from 42 to 7). I can't figure out why this is happening. Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <sys/types.h>
#include <unistd.h>
struct pair{
int a;
int b;
}pair_t;
int main(){
int N;
int numPrimes = 1;
int *primes = malloc(100*sizeof(int));
int isPrime = 1;
primes[0] = 2;
int timesRealloc = 0;
int availableSlots = 100;
printf("Please enter the largest even number you want to find the Goldbach pair for: \n");
scanf("%d", &N);
struct pair pairs[N/2 + 4];
int j = 0;
int i;
for (i = 3; i <= N; i+=2){
j = 0;
isPrime = 1;
while (primes[j] <= sqrt(i)) {
if (i%primes[j] == 0) {
isPrime = 0;
break;
}
j++;
}
if (isPrime == 1){
primes[numPrimes] = i;
numPrimes++;
}
if (availableSlots == numPrimes){
timesRealloc++;
availableSlots += 100;
primes = realloc(primes, availableSlots*sizeof(int));
}
}
printf("The largest prime I found was %d\n", primes[(numPrimes-1)]);
int k;
for (i=4; i<=N; i+=2){
printf("i is %d, N is %d\n", i, N);
if (i > N){ break; }
for (j=0; j<numPrimes; j++){
for (k=0; k<numPrimes; k++){
int sum = primes[j] + primes[k];
if(sum == i){
pairs[i].a = primes[j];
pairs[i].b = primes[k];
}
}
}
}
for (i=4; i<=N; i+=2){
printf("%d is the sum of %d and %d\n", i, pairs[i].a, pairs[i].b);
}
return 0;
}
You attempt to be space efficient by compressing the pairs array to just hold every other (even) number and start from 4 instead of zero. However, you miscalculate its size and then when you go to use it, you treat it like it hasn't been compressed and that there's a slot for every natural number.
The code suffers from having the prime array calculation in main() along with the other code, this is best separated out. And when it looks for pairs, it doesn't quit when it finds one, nor when it starts getting sums greater than the target. My rework below attempts to address all of these issues:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <stdbool.h>
#define INITIAL_SLOTS (100)
struct pair {
int a;
int b;
} pair_t;
int compute_primes(int limit, unsigned **primes, int size) {
int numPrimes = 0;
(*primes)[numPrimes++] = 2;
for (int i = 3; i <= limit; i += 2) {
bool isPrime = true;
for (int j = 0; (*primes)[j] <= i / (*primes)[j]; j++) {
if (i % (*primes)[j] == 0) {
isPrime = false;
break;
}
}
if (isPrime) {
(*primes)[numPrimes++] = i;
}
if (numPrimes == size) {
size *= 2;
*primes = realloc(*primes, size * sizeof(unsigned));
}
}
return numPrimes;
}
int main() {
int N;
printf("Please enter the largest even number you want to find the Goldbach pair for: \n");
scanf("%d", &N);
unsigned *primes = calloc(INITIAL_SLOTS, sizeof(unsigned));
int numPrimes = compute_primes(N, &primes, INITIAL_SLOTS);
printf("The largest prime I found was %d\n", primes[numPrimes - 1]);
struct pair pairs[(N - 4) / 2 + 1]; // compressed data structure
for (int i = 4; i <= N; i += 2) {
int offset = (i - 4) / 2; // compressed index
bool found = false;
for (int j = 0; ! found && j < numPrimes; j++) {
for (int k = 0; ! found && k < numPrimes; k++) {
int sum = primes[j] + primes[k];
if (sum == i) {
pairs[offset].a = primes[j];
pairs[offset].b = primes[k];
found = true;
} else if (sum > i) {
break;
}
}
}
}
for (int i = 4; i <= N; i += 2) {
int offset = (i - 4) / 2; // compressed index
printf("%d is the sum of %d and %d\n", i, pairs[offset].a, pairs[offset].b);
}
free(primes);
return 0;
}
OUTPUT
> ./a.out
Please enter the largest even number you want to find the Goldbach pair for:
10000
The largest prime I found was 9973
4 is the sum of 2 and 2
6 is the sum of 3 and 3
8 is the sum of 3 and 5
10 is the sum of 3 and 7
12 is the sum of 5 and 7
14 is the sum of 3 and 11
...
9990 is the sum of 17 and 9973
9992 is the sum of 19 and 9973
9994 is the sum of 53 and 9941
9996 is the sum of 23 and 9973
9998 is the sum of 31 and 9967
10000 is the sum of 59 and 9941
>
So, I tried to implement the Middle Square PRNG method, to generate the first 100 numbers. It works well until a certain point, when I get as a result negative numbers.
I used the time library to change the values on my temp array, so that it won't get stuck on the same sequence, where the number ends with two zeros.
My code :
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
time_t now;
struct tm *tm;
unsigned long int prng(int seed)
{
int num = seed * seed;
int t[10], inc = 0;
//Reverse number in an array
while(num != 0)
{
t[inc] = num%10;
num /= 10;
inc++;
}
int min = inc/4;
int max = inc / 2 + min;
int temp[10];
//Assign the middle square part to another table
for(int i = min; i <= max; i++)
{
temp[i-min] = t[i];
}
for(int i=0; i < max-min; i++)
{
//Check if there is a "0" "0" sequence, if TRUE - replace with current time (seconds)
if(temp[i] == 0 && temp[i+1] == 0)
{
now = time(0);
tm = localtime(&now);
temp[i] = tm->tm_sec/10;
temp[i + 1] = tm->tm_sec%10;
}
}
//Transform the squared array into an integer
unsigned long int k = 0;
for (int i = 0; i <= max-min; i++)
k = 10 * k + temp[i];
return k;
}
int main()
{
unsigned long int n = 123; //seed
printf("%d ", n);
for(int i = 0; i<100; i++)
{
n = prng(n);
printf("\n%d ", n);
}
return 0;
}
The results that I get:
123
215
226
701
419
6557
24992
7064
7099
85930
-696950
8997
6490
10212
94824
36561
760763
-724206
30238
66334
22325
65048
-94273
...
I am a newbie to threading and i am trying to change the sequential program of travelling salesman problem (dynamic programming) to parallel program using threading in c.
#include <stdio.h>
#include <limits.h>
#define size 10 //maximum 10 cities
#define min(a,b) (a > b ? b : a)
#define sizePOW 1024 // 2^10
//Space complexity: O(n * 2^n)
//Time complexity: O(n^2 * 2^n)
int n; npow;
int g[size][sizePOW];
int p[size][sizePOW];
int adj[size][size];
int compute(int start, int set) {
int masked, mask, temp, i;
int result = INT_MAX; //result stores the minimum
if (g[start][set] != -1) //memoization DP top-down,check for repeated subproblem
return g[start][set];
for (i = 0; i < n; i++) { //npow-1 because we always exclude "home" vertex from our set
mask = (npow - 1) - (1 << i); //remove ith vertex from this set
masked = set & mask;
if (masked != set) { //in case same set is generated(because ith vertex was not present in the set hence we get the same set on removal) eg 12&13=12
temp = adj[start][i] + compute(i, masked); //compute the removed set
if (temp < result)
result = temp,
p[start][set] = i; //removing ith vertex gave us minimum
}
}
return g[start][set] = result; //return minimum
}
void getpath(int start, int set) {
if (p[start][set] == -1)
return; //reached null set
int x = p[start][set];
int mask = (npow - 1) - (1 << x);
int masked = set & mask; //remove p from set
printf("%d ", x);
getpath(x, masked);
}
void TSP() {
int i, j;
//g(i,S) is length of shortest path starting at i visiting all vertices in S and ending at 1
for (i = 0; i < n; i++)
for (j = 0; j < npow; j++)
g[i][j] = p[i][j] = -1;
for (i = 0; i < n; i++)
g[i][0] = adj[i][0]; //g(i,nullset)= direct edge between (i,1)
int result = compute(0, npow - 2);//npow-2 to exclude our "home" vertex
printf("Tour cost:%d\n", result);
printf("Tour path:\n0 ");
getpath(0, npow - 2);
printf("0\n");
}
int main(void) {
int i, j;
printf("Enter number of cities\n");
scanf("%d",&n);
npow=(int)pow(2, n);//bit number required to represent all possible sets
printf("Enter the adjacency matrix\n");
for(i = 0; i < n; i++)
for(j = 0; j < n; j++)
scanf("%d", &adj[i][j]);
TSP();
return 0;
}
This is the sequential program from ideone code.
Here is my parallel code for this
#include <stdio.h>
#include <math.h>
#include <pthread.h>
#include <signal.h>
#include <errno.h>
#include <unistd.h>
#include<limits.h>
#define size 10 //maximum 10 cities
#define min(a,b) a > b ? b:a
#define sizePOW 1024 // 2^10
struct threadargs {
int a, b;
int *c;
};
//Space complexity: O(n * 2^n)
//Time complexity: O(n^2 * 2^n)
int n, npow;
int g[size][sizePOW];
int p[size][sizePOW];
int adj[size][size];
void printMatrix() {
int i, j;
for (i = 0; i < 4; i++) {
for (j = 0; j < 16; j++) {
printf("%d ",g[i][j]);
printf("\n");
}
printf("\n\n");
}
void *compute(void *args) {
int masked, mask, i, start, set;
int result = INT_MAX; //result stores the minimum
struct threadargs *recvargs = (struct threadargs *) args;
start = recvargs->a;
set = recvargs->b;
int *retval = recvargs->c;
if (g[start][set] != -1) { //memoization DP top-down,check for repeated subproblem
*retval += g[start][set];
return;
}
printMatrix();
//sleep(1);
int temp[n];
for (i = 0; i < n; i++)
temp[i] = INT_MAX;
pthread_t threads[n];
struct threadargs arguments[n];
int running_thread_count = 0;
for (i = 0; i < n; i++)
threads[i] == -1;
for (i = 0; i < n; i++) { //npow-1 because we always exclude "home" vertex from our set
mask= (npow - 1) - (1 << i); //remove ith vertex from this set
masked = set & mask;
//printf("hello world");
if (masked != set)//in case same set is generated(because ith vertex was not present in the set hence we get the same set on removal) eg 12&13=12
{
temp[i] = adj[start][i];
arguments[i].a = i;
arguments[i].b = masked;
arguments[i].c = &temp[i];
pthread_create(&threads[i], NULL, compute, (void *)&arguments[i] );
running_thread_count++;
}
}
for (i = 0; i < n; i++) {
if (pthread_kill(threads[i], 0) != ESRCH)
pthread_join(threads[i], NULL);
}
int ith = 0;
result = temp[0];
for (i = 1; i < n; i++) {
if(temp[i] < result) {
result = temp[i];
ith = i;
}
}
p[start][set] = ith;
if (result != INT_MAX)
g[start][set] = result; //return minimum
*retval += g[start][set];
}
void getpath(int start,int set)
{
if (p[start][set] == -1)
return; //reached null set
int x = p[start][set];
int mask= (npow - 1) - (1 << x);
int masked = set & mask;//remove p from set
printf("%d ",x);
getpath(x, masked);
}
void TSP()
{ int i, j;
//g(i,S) is length of shortest path starting at i visiting all vertices in S and ending at 1
for(i=0; i < n; i++)
for( j = 0; j < npow; j++)
g[i][j] = p[i][j] = -1;
for (i = 0; i < n; i++)
g[i][0] = adj[i][0]; //g(i,nullset)= direct edge between (i,1)
int result;
struct threadargs arguments;
arguments.a = 0;
arguments.b = npow-2;
arguments.c = &result;
compute((void *) &arguments);//npow-2 to exclude our "home" vertex
printf("Tour cost:%d\n",result);
printf("Tour path:\n0 ");
getpath(0,npow-2);
printf("0\n");
}
int main(void) {
int i, j;
printf("Enter number of cities\n");
scanf("%d", &n);
npow=(int)pow(2, n);//bit number required to represent all possible sets
printf("Enter the adjacency matrix\n");
for (i = 0; i < n; i++)
for (j = 0; j < n; j++)
scanf("%d", &adj[i][j]);
TSP();
return 0;
}
But I am getting segmentation fault while trying to execute this code. Following is the output of the gdb
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff78bf63e in pthread_join (threadid=4196128,
thread_return=0x0) at pthread_join.c:85
85 pthread_join.c: No such file or directory.
(gdb) backtrace
#0 0x00007ffff78bf63e in pthread_join (threadid=4196128,
thread_return=0x0) at pthread_join.c:85
#1 0x0000000000400b36 in compute (args=0x7fffffffde90) at tsp3.c:69
#2 0x0000000000400db2 in TSP () at tsp3.c:107
#3 0x0000000000400ec8 in main () at tsp3.c:120
(gdb)
I know this will not give any noticeable performance gain but I want to try this. Thanks in advance.
**edit : **
I have rectified the errors but now I am facing new errors.I am getting correct answer when program runs but if I delete the line `printMatrix()
, I get segmentation fault. The gdb log is as follows
(gdb) backtrace
#0 __pthread_kill (threadid=0, signo=0)
at ../nptl/sysdeps/unix/sysv/linux/pthread_kill.c:42
#1 0x0000000000400c85 in compute (args=0x7ffff74eede0) at tsp3.c:79
#2 0x00007ffff78be182 in start_thread (arg=0x7ffff64ed700)
at pthread_create.c:312
#3 0x00007ffff75eaefd in clone ()
at ../sysdeps/unix/sysv/linux/x86_64/clone.S:111
(gdb)
why is this happening. Please explain. Thanks in advance.
You are creating threads in compare function, and you pass compare as thread function, that's chaos. You maybe exceed available number of threads.
int i,j,vec[15]={0};
srand (time(NULL));
for (i=0;i<15;i++){
vec[i]=rand() % 25+1;
for (j=0;j<15;j++){
if (i!=j){
while(vec[i]==vec[j]){
vec[i]=rand() % 25+1;
}
}
}
printf("%d\n",vec[i]);
}
return 0;
}
the code still gives me repeated numbers
EXAMPLE:
24
3
7
20
18
10
12
17
9
7
4
25
13
15
21
I cant figure out what to do with it
You have your loops mixed up. The logic is: Generate a random number until you have found one that isn't in the list.
The way you do it, you generate a new number inside the checking loop. But that doesn't work. Say you're generating the 4th number and find it is equal to the third. Then you generate a new one which might well be equal to any you have already checked against.
You also check uninitialised elements when j > i. Your inner loop should only run up to i.
So:
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
int main()
{
int vec[15] = { 0 };
int i, j;
srand(time(NULL));
for (i = 0; i < 15; i++) {
int okay = 0;
while (!okay) {
vec[i] = rand() % 25 + 1;
okay = 1;
for (j = 0; j < i; j++) {
if (vec[i] == vec[j]) okay = 0;
}
}
printf("%d\n", vec[i]);
}
return 0;
}
That still looks a bit awkward with that okay variable. In my opinion, checking for duplicates should be a separate function:
int contains(int arr[], int n, int x)
{
while (n--) {
if (arr[n] == x) return 1;
}
return 0;
}
int main()
{
// snip ...
for (i = 0; i < 15; i++) {
do {
vec[i] = rand() % 25 + 1;
} while (contains(vec, i, vec[i]));
printf("%d\n", vec[i]);
}
// snip ...
}
In your case the range of possible numbers isn't mich bigger than the number of array elements. You could also create an ordered array {1, 2, 3, ..., 25}, then shuffle it and use only the first 15 elements.
Reset j in the while loop:
for (j=0;j<i;j++){ //Use j<i
if (i!=j){
while(vec[i]==vec[j]){
vec[i]=rand() % 25+1;
j=-1;//-1 because in the next iteration,j will start from 0
}
}
}
Are you actually trying to shuffle the numbers, rather than fill the array with randoms? (It looks like you want an array with numbers from 1 to 25, but in random order.) rand() can give you duplicate numbers (they're random, after all!)
Try this:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
int
main( int argc, char **argv )
{
int i, vec[25];
for (i = 0; i < 25; ++i) vec[i] = i + 1;
/* Shuffle entries */
srand( time( 0 ) );
for (i = 0; i < 1000; ++i) {
int a = rand( ) % 25;
int b = rand( ) % 25;
if (a != b) {
int tmp = vec[a];
vec[a] = vec[b];
vec[b] = tmp;
}
}
/* Print shuffled array */
for (i = 0; i < 25; ++i) printf( "%d: %d\n", i, vec[i] );
return 0;
}
#include<stdio.h>
#include<stdlib.h>
int inArray(int, int, int*);
int main()
{
int i,j,vec[15]={0};
int temp;
srand (time(NULL));
for (i=0;i<15;i++){
temp =rand() % 25+1;
while(inArray(i+1,temp, vec) == 1){
temp = rand() % 25+1;
}
vec[i] = temp;
printf("VECT[%d] \t= %d\n",i,vec[i]);
}
return 0;
}
int inArray(int count, int input, int* array){
int i = 0;
for(i=0; i<count; i++){
if(input == array[i]){
return 1;
}
}
return 0;
}
Gave an output:
VECT[0] = 24
VECT[1] = 19
VECT[2] = 1
VECT[3] = 25
VECT[4] = 22
VECT[5] = 18
VECT[6] = 7
VECT[7] = 8
VECT[8] = 12
VECT[9] = 21
VECT[10] = 11
VECT[11] = 6
VECT[12] = 23
VECT[13] = 20
VECT[14] = 15
The checking was off, you would change and not break allowing it to be changed to a previous value.
You can use an array
int randNumbers[25]; // fill it starting 0 to 25 then
randomize the number in a range between 0 and 25 after swap the number in the randomized index with the last number in your array
randomize 0 to 23
and so on....
int main(int argc, char **argv) {
static const int size = 25;
int numbers[size];
for( int i = 0; i < size; i++ ){
numbers[i] = i;
}
srand (time(NULL));
for( int i = 0; i < size; i++ ){
int rIndex = rand()%(size - i);
int rNum = numbers[rIndex];
numbers[rIndex] = numbers[size-i];
printf("%d ", rNum);
}
return 0;
}
O(n) complexity...