Multithreaded Sorting Application - c

I am new to multithreaded programming and so I thought I would work on a project to help me learn it. Here are the details of the project:
Write a multithreaded sorting program in c that works as follows: A list of integers is divided into two smaller lists of equal size. Two separate threads (which we will term sorting threads) sort each sublist using a sorting algorithm of your choice. The two sublists are then merged by a third thread - a merging thread - which merges the two sublists into a single sorted list.
//Sort a list of numbers using two separate threads
//by sorting half of each list separately then
//recombining the lists
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#define SIZE 10
#define NUMBER_OF_THREADS 3
void *sorter(void *params); /* thread that performs basic sorting algorithm */
void *merger(void *params); /* thread that performs merging of results */
int list[SIZE] = {7,12,19,3,18,4,2,6,15,8};
int result[SIZE];
typedef struct
{
int from_index;
int to_index;
} parameters;
int main (int argc, const char * argv[])
{
int i;
pthread_t workers[NUMBER_OF_THREADS];
/* establish the first sorting thread */
parameters *data = (parameters *) malloc (sizeof(parameters));
data->from_index = 0;
data->to_index = (SIZE/2) - 1;
pthread_create(&workers[0], 0, sorter, data);
/* establish the second sorting thread */
data = (parameters *) malloc (sizeof(parameters));
data->from_index = (SIZE/2);
data->to_index = SIZE - 1;
pthread_create(&workers[1], 0, sorter, data);
/* now wait for the 2 sorting threads to finish */
for (i = 0; i < NUMBER_OF_THREADS - 1; i++)
pthread_join(workers[i], NULL);
/* establish the merge thread */
data = (parameters *) malloc(sizeof(parameters));
data->from_index = 0;
data->to_index = (SIZE/2);
pthread_create(&workers[2], 0, merger, data);
/* wait for the merge thread to finish */
pthread_join(workers[2], NULL);
/* output the sorted array */
return 0;
}
void *sorter(void *params)
{
parameters* p = (parameters *)params;
//SORT
int begin = p->from_index;
int end = p->to_index+1;
int z;
for(z = begin; z < end; z++){
printf("The array recieved is: %d\n", list[z]);
}
printf("\n");
int i,j,t,k;
for(i=begin; i< end; i++)
{
for(j=begin; j< end-i-1; j++)
{
if(list[j] > list[j+1])
{
t = list[j];
list[j] = list[j+1];
list[j+1] = t;
}
}
}
for(k = begin; k< end; k++){
printf("The sorted array: %d\n", list[k]);
}
int x;
for(x=begin; x<end; x++)
{
list[x] = result[x];
}
printf("\n");
pthread_exit(0);
}
void *merger(void *params)
{
parameters* p = (parameters *)params;
//MERGE
int begin = p->from_index;
int end = p->to_index+1;
int i,j,t;
printf("list[1]: %d",list[1]);
printf("result[1]: %d",result[1]);
for(i=begin; i< end; i++)
{
for(j=begin; j< end-i; j++)
{
if(result[j] > result[j+1])
{
t = result[j];
result[j] = result[j+1];
result[j+1] = t;
}
}
}
int d;
for(d=0; d<SIZE; d++)
{
printf("The final resulting array is: %d\n", result[d]);
}
pthread_exit(0);
}
I'm not sure what I'm doing wrong in my algorithms that its not working. It doesn't seem to catch the new sorted array. Any help on this problem would be appreciated VERY much! Thanks again in advance for all your help!

Your approach is incorrect. You should be splitting your partitions, then recursing or threading into them, joining the results, then merging. Its easy to screw this algorithm up, believe me.
Before anything else, make sure your merge algorithm is solid. If your merge has issues in a single-threaded arena, adding threads is only going to make it worse. In your case, you're making it worse because your merge thread appears to be running concurrently with your sorter threads.
That said, step back and consider this. Mergesort is about divide and conquer. To thread up a merge sort you should be doing the following:
Establish a maximum number of threads. Believe me, the last thing you want happening is spinning a thread for each partition. a sequence of 1024 values has 1023 partitions if you crunch the math hard enough. that many threads is not a solution. Establish some boundaries.
Establish a minimum partition size that you're willing to spin a thread for. This is as important as the first item above. Just like you don't want to be spinning 1023 threads to sort a 1024-slot sequence, you also don't want to be spinning a thread just to sort a sequence that has two items. There is zero benefit and much cost.
Have a solid merge algorithm. There are many efficient ways to do it, but do something simple and enhance it later. Right now we're just interested in getting the general threading down right. There is always time to enhance this with a fancy merge algorithm (like in-place, which believe me is harder than it sounds).
Having the above the idea is this:
The merge sort algorithm will have three parameters: a starting pointer, a length, and a thread-depth. For our purposes the thread depth will be N in a situation where we are using at-most 2N-1 threads. (more on that later, but trust me, it makes it easier to do the math this way).
If the thread depth has reached zero OR the sequence length is below a minimum threshold *we set), do not setup and run a new thread. Just recurse into our function again.
Otherwise, split the partition. Setup a structure that holds a partition definition (which for us will be a starting point and a length as well as the thread depth which will be N/2), launch a thread with that parameter block, then do NOT launch another thread. instead use the current thread to recurse into merge_sort_mt() for the "other" half.
Once the current thread returns from its recursion is must wait on the other thread via a join. once that is done both partitions will be done and they can be merged using your trivial merge algorithm.
Whew. Ok. so how does it look in practice:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <pthread.h>
struct Params
{
int *start;
size_t len;
int depth;
};
// only used for synchronizing stdout from overlap.
pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
// forward declare our thread proc
void *merge_sort_thread(void *pv);
// a simple merge algorithm. there are *several* more efficient ways
// of doing this, but the purpose of this exercise is to establish
// merge-threading, so we stick with simple for now.
void merge(int *start, int *mid, int *end)
{
int *res = malloc((end - start)*sizeof(*res));
int *lhs = start, *rhs = mid, *dst = res;
while (lhs != mid && rhs != end)
*dst++ = (*lhs < *rhs) ? *lhs++ : *rhs++;
while (lhs != mid)
*dst++ = *lhs++;
// copy results
memcpy(start, res, (rhs - start) * sizeof *res);
free(res);
}
// our multi-threaded entry point.
void merge_sort_mt(int *start, size_t len, int depth)
{
if (len < 2)
return;
if (depth <= 0 || len < 4)
{
merge_sort_mt(start, len/2, 0);
merge_sort_mt(start+len/2, len-len/2, 0);
}
else
{
struct Params params = { start, len/2, depth/2 };
pthread_t thrd;
pthread_mutex_lock(&mtx);
printf("Starting subthread...\n");
pthread_mutex_unlock(&mtx);
// create our thread
pthread_create(&thrd, NULL, merge_sort_thread, &params);
// recurse into our top-end parition
merge_sort_mt(start+len/2, len-len/2, depth/2);
// join on the launched thread
pthread_join(thrd, NULL);
pthread_mutex_lock(&mtx);
printf("Finished subthread.\n");
pthread_mutex_unlock(&mtx);
}
// merge the partitions.
merge(start, start+len/2, start+len);
}
// our thread-proc that invokes merge_sort. this just passes the
// given parameters off to our merge_sort algorithm
void *merge_sort_thread(void *pv)
{
struct Params *params = pv;
merge_sort_mt(params->start, params->len, params->depth);
return pv;
}
// public-facing api
void merge_sort(int *start, size_t len)
{
merge_sort_mt(start, len, 4); // 4 is a nice number, will use 7 threads.
}
int main()
{
static const unsigned int N = 2048;
int *data = malloc(N * sizeof(*data));
unsigned int i;
srand((unsigned)time(0));
for (i=0; i<N; ++i)
{
data[i] = rand() % 1024;
printf("%4d ", data[i]);
if ((i+1)%8 == 0)
printf("\n");
}
printf("\n");
// invoke our multi-threaded merge-sort
merge_sort(data, N);
for (i=0; i<N; ++i)
{
printf("%4d ", data[i]);
if ((i+1)%8 == 0)
printf("\n");
}
printf("\n");
free(data);
return 0;
}
The output for this looks something like this:
825 405 691 290 900 715 125 969
534 809 783 820 933 895 310 687
152 19 659 856 46 765 497 371
339 660 297 509 152 796 230 465
502 948 278 317 144 941 195 208
617 428 118 505 719 161 53 292
....
994 154 745 666 590 356 894 741
881 129 439 237 83 181 33 310
549 484 12 524 753 820 443 275
17 731 825 709 725 663 647 257
Starting subthread...
Starting subthread...
Starting subthread...
Starting subthread...
Starting subthread...
Starting subthread...
Starting subthread...
Finished subthread.
Finished subthread.
Finished subthread.
Finished subthread.
Finished subthread.
Finished subthread.
Finished subthread.
0 0 1 1 1 2 3 3
5 5 5 5 6 6 7 7
7 7 7 8 8 10 10 11
11 11 12 12 12 13 14 14
15 15 15 15 16 17 17 17
17 18 18 19 19 19 20 21
21 21 22 22 23 24 24 24
25 25 25 26 26 28 28 29
29 29 30 30 30 30 30 31
....
994 995 996 998 1000 1001 1001 1003
1003 1003 1003 1004 1004 1005 1007 1007
1010 1010 1010 1010 1011 1012 1012 1012
1012 1013 1013 1013 1015 1015 1016 1016
1016 1017 1018 1019 1019 1019 1020 1020
1020 1021 1021 1021 1021 1022 1023 1023
The most important part of this is the limiters that keep us from going thread-wild (which is easy to accidentally do with recursive threaded algorithms), and the join of the threads before merging their content with the other half of the partition (which we sorted on our thread, and may also have done the same thing).
It's a fun exercise, and I hope you got something out of it. Best of luck.
Update: Integrating qsort()
An interesting task would be performing this functionality using qsort() for sorting the smaller partitions or once the thread pool reaches exhaustion. qsort() is a pretty big hammer to bring to this party, and as such you're going to want to raise the minimum partition size to something respectful (in the example below, we use 256 elements).
So what would it take to integrate qsort() the the sub partitions rather than a hand-rolled merge-sort? Surprisingly, not much. Start with a qsort() compatible comparator:
// comparator for qsort
int cmp_proc(const void *arg1, const void* arg2)
{
const int *lhs = arg1;
const int *rhs = arg2;
return (*lhs < *rhs) ? -1 : (*rhs < *lhs ? 1 : 0);
}
Pretty brain-dead. Now, modify the mt-wrapper to look something like this:
// our multi-threaded entry point.
void merge_sort_mt(int *start, size_t len, int depth)
{
if (len < 2)
return;
// invoke qsort on the partition. no need for merge
if (depth <= 0 || len <= 256)
{
qsort(start, len, sizeof(*start), cmp_proc);
return;
}
struct Params params = { start, len/2, depth/2 };
pthread_t thrd;
pthread_mutex_lock(&mtx);
printf("Starting subthread...\n");
pthread_mutex_unlock(&mtx);
// create our thread
pthread_create(&thrd, NULL, merge_sort_thread, &params);
// recurse into our top-end parition
merge_sort_mt(start+len/2, len-len/2, depth/2);
// join on the launched thread
pthread_join(thrd, NULL);
pthread_mutex_lock(&mtx);
printf("Finished subthread.\n");
pthread_mutex_unlock(&mtx);
// merge the paritions.
merge(start, start+len/2, start+len);
}
That's it. Seriously. That is all it takes. Proving this works is a simple test run with the original program, shown below:
986 774 60 596 832 171 659 753
638 680 973 352 340 221 836 390
930 38 564 277 544 785 795 451
94 602 724 154 752 381 433 990
539 587 194 963 558 797 800 355
420 376 501 429 203 470 670 683
....
216 748 534 482 217 178 541 242
118 421 457 810 14 544 100 388
291 29 562 718 534 243 322 187
502 203 912 717 1018 749 742 430
172 831 341 331 914 866 931 368
Starting subthread...
Starting subthread...
Starting subthread...
Starting subthread...
Starting subthread...
Starting subthread...
Starting subthread...
Finished subthread.
Finished subthread.
Finished subthread.
Finished subthread.
Finished subthread.
Finished subthread.
Finished subthread.
0 0 1 1 1 1 3 3
3 4 5 5 6 6 6 6
7 7 8 9 10 10 10 10
11 12 12 12 13 13 14 14
14 15 15 15 16 17 17 19
19 20 20 21 21 21 22 22
23 23 23 24 24 24 25 26
26 26 26 27 28 28 28 28
....
1000 1000 1000 1001 1001 1002 1003 1003
1004 1004 1004 1005 1005 1005 1006 1007
1008 1010 1010 1010 1010 1010 1011 1011
1011 1012 1012 1012 1012 1013 1013 1013
1015 1015 1015 1016 1016 1017 1017 1017
1018 1018 1018 1019 1019 1021 1021 1022
As you can see, the results are similar.

A couple of issues:
1 - What do you think this code is doing:
int x;
for(x=begin; x<end; x++)
{
list[x] = result[x];
}
2 - Your merger currently looks exactly like your sorter. It should instead be merging the sorted values from the first half of the list and the second half of the list into the result.

Your code is correct i have modified your code and tried to figure out the error,
the loop indexes are not correctly mapped and you are assigning the null result list into actual data in one loop, so the list is taking zeroes.
Find below the modified code and output.
//Sort a list of numbers using two separate threads
//by sorting half of each list separately then
//recombining the lists
void *sort(void *params)
{
parameters* p = (parameters *)params;
//SORT
int begin = p->fromVal;
int end = p->toVal+1;
for(int i = begin; i < end; i++){
printf("The array recieved is: %d\n", list[i]);
}
printf("\n");
int temp=0;
for(int i=begin; i< end; i++)
{
for(int j=begin; j< end-1; j++)
{
if(list[j] > list[j+1])
{
temp = list[j];
list[j] = list[j+1];
list[j+1] = temp;
}
}
}
for(int k = begin; k< end; k++){
printf("The sorted array: %d\n", list[k]);
}
for(int i=begin; i<end; i++)
{
result[i] = list[i];
}
printf("\n");
pthread_exit(NULL);
}
void *merging(void *params)
{
parameters* p = (parameters *)params;
//MERGE
int begin = p->fromVal;
int end = p->toVal+1;
int temp;
for(int i=begin; i< end; i++)
{
for(int j=begin; j< end-1; j++)
{
if(result[j] > result[j+1])
{
temp= result[j];
result[j] = result[j+1];
result[j+1] = temp;
}
}
}
printf("\n\nFINAL RESULT IS:\n");
for(int d=begin+1; d<end; d++)
{
printf("The final resulting array is: %d\n", result[d]);
}
pthread_exit(NULL);
}

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <time.h>
/*globle variables*/
/* structure for passing data to threads */
typedef struct
{
int *start;
int end;
int size;
} parameters;
int t = 1;
int *arr1, *arr2;
//for using quicksort
int comparator (const void * a, const void * b) {
return ( *(int*)a - *(int*)b );
}
void *merge(void *params){
//get data
int *len = params;
//SORT
int start = 0;
int end = *len/2;
int counter = end;
int size = *len;
int index = 0;
while (start < end && counter < size)
{
if (arr1[start] < arr1[counter])
{
arr2[index] = arr1[start];
start ++;
}
else
{
arr2[index] = arr1[counter];
counter ++;
}
index ++;
}
/* Copy the remaining elements , if there
are any */
while ( start < end)
{
arr2[index] = arr1[start];
start ++;
index ++;
}
/* Copy the remaining elements , if there
are any */
while ( counter < size)
{
arr2[index] = arr1[counter];
counter ++;
index ++;
}
}
void *sorting_thread(void *params){
printf("Thread %d ......\n", t);
t++;
//get data
parameters* data = (parameters *)params;
//SORT
int end = data->end;
int size = data->size;
//qsort
qsort(data->start, end, sizeof(*data->start), comparator);
printf("The array after sort : \n");
for(int i = size - end; i < size; i ++){
printf("arr1[%d]:%d, \n", i,arr1[i]);
}
printf("\n");
pthread_exit(0);
}
void *merge_sort_thread(void *params){
int *len = params;
//varaible allocation for two sorting threads.
parameters *data = (parameters *) malloc (sizeof(parameters));
parameters *data1 = (parameters *) malloc (sizeof(parameters));
if(data == NULL&& data1 == NULL){
printf("Memory not allocated. \n");
exit(0);
}
//value for data passing
data->start= arr1;
data->end = *len/2;
data->size = *len/2;
data1->start = arr1 + *len/2;
data1->end = *len-*len/2;
data1->size = *len;
pthread_t left, right;/* the thread identifier */
printf("Entering merge_Sorting..\n");
/* create the sorting thread */
pthread_create(&left, NULL, sorting_thread, data);
pthread_create(&right, NULL, sorting_thread, data1);
/* wait for the thread to exit */
pthread_join(left, NULL);
//free memory
free(data);
pthread_join(right, NULL);
printf("Merging Thread %d ......\n", t);
merge(len);
printf("Process is done.\n");
printf("The final output: \n");
for(int i = 0; i < *len; i ++){
if(i%10==0){
printf("\n");
}
printf("%d, ", arr2[i]);
}
printf("\n");
//free memory
free(data1);
pthread_exit(0);
}
int main( int argc, char *argv[] ) {
long len;
int temp, c, j, k;
char *ptr;
//
//check if the right amount of argument
if( argc == 2 ) {
printf("The input array size is %s\n", argv[1]);
//covert the user input to integer
len = strtol(argv[1], &ptr, 10);
//check if the input is valid.
if(len == 0) {//if not, leave the program.
printf("Please enter a proper number. Leaving the program...\n");
}else{
//dynamically allocate memory
arr1 = (int*)malloc(len * sizeof(int));
arr2 = (int*)malloc(len * sizeof(int));
//check Memory
if(arr1 == NULL && arr2 == NULL){
printf("Memory not allocated. \n");
exit(0);
}
printf("Memory allocated. \n");
//decide the value of data.
//generate random number to 100
srand(time(0));
printf("The array before sorting is: \n");
for(int i = 0; i < len; i ++){
arr1[i] = rand() % 100;
if(i%10==0){
printf("\n");
}
printf("%d, ", arr1[i]);
}
printf(" \n");
//merge sort handle all the threads
pthread_t tid;/* the thread identifier */
/* create the parent sorting thread */
pthread_create(&tid, NULL, merge_sort_thread, &len);
//wait for children thread
pthread_join(tid, NULL);
//printout array after merging threading
printf("\nThe program is finished. \n");
//free memory space
free(arr2);
free(arr1);
}
}
else if( argc > 2 ) {
printf("Too many arguments supplied.\n");
}
else {
printf("One argument expected.\n");
}
return 0;
}

Related

First threads in array of threads getting skipped in c (sometimes)?

I am trying to write a multithreaded program in C that sorts an array by breaking it up into partitions, and then each thread works on it's own partition. The problem seems to be that sometimes Thread 1, and sometimes Thread 2, get skipped in execution. I haven't even gotten to the sorting, just the comparison. For now i just want to know my threads are running correctly, but it seems the first ones can just not get scheduled or something. I am not very strong with C, and am really racking my brain for what can be going wrong.
I know each thread can be paused by the scheduler, but they all should eventually get completed right? So why does my first couple threads sometimes not run?
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <time.h>
#define SIZE 11
#define HM_SORTERS 4
void * sort(void * param);
void printArr(int * arr);
struct PartitionBounds {
int tid;
size_t start;
size_t end;
};
int array[SIZE] = {18, 12, 68, 59, 75, 73, 68, 4, 16, 94, 15};
int main() {
// srand(time(NULL));
// for (size_t i = 0; i < SIZE; i++) {
// array[i] = rand() % 100;
// }
printArr(array);
pthread_t sorters[HM_SORTERS];
for(int i=0;i<HM_SORTERS;i++) {
struct PartitionBounds bounds;
size_t coverage = SIZE / HM_SORTERS;
bounds.tid = i;
bounds.start = i * coverage;
bounds.end = i + 1 == HM_SORTERS ? SIZE - 1 : bounds.start + coverage - 1;
int status = pthread_create(&sorters[i], NULL, sort, &bounds);
if(status == 0) {
printf("\n--- Thread %d created successfully ---\n", i + 1);
printf("start: %zu, end: %zu\n", bounds.start, bounds.end);
} else {
printf("!!! Failed to create thread !!!\n");
return 0;
}
}
for(int i=0;i<HM_SORTERS;i++) {
pthread_join(sorters[i], NULL);
}
printf("\n\n----- Sorting completed -----\n\n");
return 0;
}
void * sort(void * param) {
struct PartitionBounds *bounds = param;
printf("\n\tin thread %d\n\n", bounds->tid + 1);
for(size_t i=bounds->start;i<=bounds->end;i++) {
for(size_t j=i+1;j<=bounds->end;j++) {
if(array[j] < array[i]) {
printf("Thread %d: %d is smaller than %d\n", bounds->tid + 1, array[j], array[i]);
}
}
}
pthread_exit(NULL);
}
void printArr(int * arr) {
int coverage = SIZE / HM_SORTERS;
for(int i=0;i<HM_SORTERS;i++) {
size_t partitionEnd = i + 1 == HM_SORTERS ? coverage + SIZE % HM_SORTERS : coverage;
for(int j=0;j<partitionEnd;j++) {
printf("%d", array[j + coverage * i]);
if(j+1 < partitionEnd) {
printf(", ");
}
}
if(i+1 < HM_SORTERS) {
printf(" | ");
}
}
printf("\n");
}
output: (typical, when threads get skipped)
18, 12 | 68, 59 | 75, 73 | 68, 4, 16, 94, 15
--- Thread 1 created successfully ---
start: 0, end: 1
--- Thread 2 created successfully ---
start: 2, end: 3
in thread 1
--- Thread 3 created successfully ---
Thread 3: 73 is smaller than 75
in thread 3
Thread 3: 73 is smaller than 75
in thread 2
start: 4, end: 5
Thread 3: 73 is smaller than 75
Thread 4: 68 is smaller than 75
Thread 4: 4 is smaller than 75
Thread 4: 16 is smaller than 75
Thread 4: 15 is smaller than 75
--- Thread 4 created successfully ---
start: 6, end: 10
Thread 4: 68 is smaller than 73
Thread 4: 4 is smaller than 73
Thread 4: 16 is smaller than 73
Thread 4: 15 is smaller than 73
Thread 4: 4 is smaller than 68
Thread 4: 16 is smaller than 68
Thread 4: 15 is smaller than 68
Thread 4: 15 is smaller than 16
Thread 4: 15 is smaller than 94
in thread 4
Thread 4: 4 is smaller than 68
Thread 4: 16 is smaller than 68
Thread 4: 15 is smaller than 68
Thread 4: 15 is smaller than 16
Thread 4: 15 is smaller than 94
----- Sorting completed -----
One problem I do see here is, referring the address of local variable.
struct PartitionBounds bounds;
int status = pthread_create(&sorters[i], NULL, sort, &bounds);
bounds is local variable and it will be vanished and new instance will be created on each iteration. Thus referring to it in sort function will have undefined behavior.
What you can do is, dynamically allocate the memory.
struct PartionBounds *bounds = malloc(sizeof(*bounds));
int status = pthread_create(&sorters[i], NULL, sort, bounds);
Make sure you free the memory once done.
An alternative solution without using malloc/free .
struct PartitionBounds bounds[HM_SORTERS];
...
size_t coverage = SIZE / HM_SORTERS;
bounds[i].tid = i;
bounds[i].start = i * coverage;
bounds[i].end = i + 1 == HM_SORTERS ? SIZE - 1 : bounds[i].start + coverage - 1;
int status = pthread_create(&sorters[i], NULL, sort, &bounds[i]);
...

Finding prime numbers using C does not work

I am currently learning C and trying to solve a problem. I need to find all the prime numbers from 2 to 100, using arrays and loops.
I already know of a solution to this problem however I am having trouble finding the error in my code. This is my first time using StackOverflow so hopefully I commented everything properly :)
#include <stdio.h>
#include <stdlib.h>
int main(){
int prime_numbers[50] = {2,3}; //initializes the array which will be printed at the end
int counter = 1; //initializes the index of the last prime element in array
int checker = 0; //initializes a checker used to determine if the number is prime
for(int i = 5; i <= 100; i++) { //goes through numbers 5 to 100 as the first two primes are hard coded
for(int j = 0; j <= counter; j++){ //goes through array untill it reaches last prime using the before initialized counter
if(i % prime_numbers[j] != 0) { //check to see if a number that is being checked is not divisible by j'th element in array
checker++; //if so, checker is incremented
}
if(checker == counter + 1) { //check to see if number was not divisible by any prime in our array
checker = 0; //if so checker is reset to 0 for the next iteration
++counter; //counter is incremented as there is one more prime in our array
prime_numbers[counter] = i; //add inside array the found prime number
break; //break should not be necessary, however for some reason, it yields a different result when I don't put it in
} //most likely the error in the code. Need to find out why loop does not stop after second if is done
}
}
for(int g = 0; g <= 50; g++) { //prints out all the prime numbers in array
if(prime_numbers[g] != 0) {
printf("%d ", prime_numbers[g]);
}
}
return 0;
}
I expect the program to print all the prime numbers from 0 to 100 with spaces in between.
The program also finds numbers that are not prime. Its logic is a rather strange inversion. The candidate needs to be divisible by only one prime in the array. The reporting also breaks the array bounds.
The corrected code:
#include <stdio.h>
int main(void) { // correct function signature
int prime_numbers[50] = {2,3};
int counter = 1;
int checker; // initialise within each loop
for(int i = 5; i <= 100; i++){
checker = 0; // inintialise here
for(int j = 0; j <= counter; j++) {
if(i % prime_numbers[j] == 0) { // opposite test to yours
checker++; // flag a non-prime
break;
}
}
if(checker == 0) { // moved outside the loop
++counter;
prime_numbers[counter] = i;
}
}
for(int g = 0; g < 50; g++) { // corrected the bounds error
if(prime_numbers[g] != 0){
printf("%d ", prime_numbers[g]);
}
}
printf("\n"); // flush the output buffer
return 0;
}
Program output:
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
The reporting loop relies on the array being initialised to 0s and a better way would be
for(int j = 0; j <= counter; j++) {
printf("%d ", prime_numbers[j]);
}
printf("\n");
The following code works well.
int main()
{
int k=1,temp,j;
const int N_prime = 10000; // number of primes to be generated
int primes[N_prime]; // array to save primes
primes[0] = 2;
primes[1] = 3;
temp = 5;
while (k!=N_prime-1){ // generating only N_prime prime numbers
for (j = 0; j <= k && primes[j] * primes[j] <= temp; j++){
if (temp%primes[j] == 0){ // if temp%primes[j] == 0 then temp is divisible by
temp += 2; // a prime and is not a prime itself, therefore
break; // immediately break
}
else if (primes[j+1] * primes[j+1]>temp){ // if no such primes found, temp is prime,
primes[k + 1] = temp; // save it and increase the value for
k++; // next check
temp += 2;
}
}
}
for (int ind = 0; ind < N_prime; ind++) printf("%d\n",primes[ind]);
getch();
return 0;
}
with the output:
2
3
5
7
11
13
17
19
23
29
31
37
41
43
47
53
59
61
67
71
73
79
83
89
97
101
103
107
109
113
127
131
137
139
149
151
157
163
167
173
179
181
191
193
197
199
211
223
227
229
233
239
241
251
257
263
269
271
277
281
283
293
307
311
313
317
331
337
347
349
353
359
367
373
379
383
389
397
401
409
419
421
431
433
439
443
449
457
461
463
467
479
487
491
499
503
509
521
523
541
As I noticed, your code generates all the odd numbers up to 100.

Threads execution Not stable

I am a beginner with threads, I have 2 arrays of floats (1024 elements each) one for real part and the other for imaginary part with which I have to do some computations.
So I thought about boosting the performance of my code by using 4 threads,and I divided my array to 4 sub-section each one of size 256 elements. So each thread is working on a part of each sub-section the arrays, for example:
Thread Nr 1 :
working on element index 0 to index 64
working on element index 256 to index 319
working on element index 512 to index 575
working on element index 768 to index 831
Thread Nr 2 :
working on element index 64 to index 127
working on element index 320 to index 383
working on element index 576 to index 639
working on element index 832 to index 895
Thread Nr 3 :
working on element index 128 to index 191
working on element index 384 to index 447
working on element index 640 to index 703
working on element index 896 to index 959
Thread Nr 4 :
working on element index 192 to index 255
working on element index 448 to index 511
working on element index 704 to index 767
working on element index 960 to index 1023
So as a try I wrote this code:
#define SHIFT_FACTOR 8
#define SIMD_SIZE 256
struct thread_data
{
unsigned start;
unsigned stop;
unsigned Twids_idx;
float* re_in;
float* im_in;
float* re_out;
float* im_out;
};
struct thread_data thread_data_array[4];
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void *thread_routine(void *thread_info)
{
int n;
unsigned t_start, t_stop, tw_offset;
unsigned ind1, ind2, ind3;
float *Re_in, *Im_in;
float *Re_out, *Im_out;
struct thread_data *mydata;
mydata = (struct thread_data*) thread_info;
t_start = mydata->start;
t_stop = mydata->stop;
Re_in = mydata->re_in;
Im_in = mydata->im_in;
Re_out = mydata->re_out;
Im_out = mydata->im_out;
for (n = t_start; n < t_stop; n += SHIFT_FACTOR)
{
pthread_mutex_lock(&mutex);
ind1 = 256 + n;
ind2 = 512 + n;
ind3 = 768 + n;
__LOAD_PS__((RE_vec_a, &Re_in[n]), SIMD_SIZE);
__LOAD_PS__((RE_vec_b, &Re_in[ind2]), SIMD_SIZE);
__LOAD_PS__((RE_vec_c, &Re_in[ind1]), SIMD_SIZE);
__LOAD_PS__((RE_vec_d, &Re_in[ind3]), SIMD_SIZE);
__LOAD_PS__((IM_vec_a, &Im_in[n]), SIMD_SIZE);
__LOAD_PS__((IM_vec_b, &Im_in[ind2]), SIMD_SIZE);
__LOAD_PS__((IM_vec_c, &Im_in[ind1]), SIMD_SIZE);
__LOAD_PS__((IM_vec_d, &Im_in[ind3]), SIMD_SIZE);
pthread_mutex_unlock(&mutex);
pthread_mutex_lock(&mutex);
__STORE_PS__((&Re_out[n], RE_vec_a), SIMD_SIZE);
__STORE_PS__((&Re_out[ind1], RE_vec_c), SIMD_SIZE);
__STORE_PS__((&Re_out[ind2], RE_vec_b), SIMD_SIZE);
__STORE_PS__((&Re_out[ind3], RE_vec_d), SIMD_SIZE);
__STORE_PS__((&Im_out[n], IM_vec_a), SIMD_SIZE);
__STORE_PS__((&Im_out[ind1], IM_vec_c), SIMD_SIZE);
__STORE_PS__((&Im_out[ind2], IM_vec_b), SIMD_SIZE);
__STORE_PS__((&Im_out[ind3], IM_vec_d), SIMD_SIZE);
pthread_mutex_unlock(&mutex);
}
pthread_exit(NULL);
}
void foo(float* data1, float* data2, float* result1, float* result2)
{
unsigned t, i = 0, tw = 0;
pthread_t threads[4];
for (t = 0; t < 256; t += 64)
{
thread_data_array[i].start = t;
thread_data_array[i].stop = t + QUARTER;
thread_data_array[i].re_in = data1;
thread_data_array[i].im_in = data2;
thread_data_array[i].re_out = result1;
thread_data_array[i].im_out = result2;
pthread_create(&threads[i], NULL, thread_routine, (void *)&thread_data_array[i]);
i++;
}
for (i = 0; i < 4; i++)
pthread_join(threads[i], NULL);
}
And as you can see I am only loading and storing in the same place the elements using some macros macros __LOAD_PS__() __STORE_PS__() which contains Intel intrinsics.
I tried to check the correctness of the execution and it turn out that on 10 tries : 7 gives me correct results and 3 partially wrong results.
Could some one please explain me what is the reason behind it?

Prime numbers in c language

I want to find prime numbers with multithreading and using Sieve of E. function.I write some piece of codes. If the program will run, the user enter a max number and thread number. The program should create threads that given thread number. The program find all prime numbers until the max number. Each thread must check one prime number.
My program doesn't find prime numbers. I write checkPrime function and crossout functions for finding prime numbers efficiently. But it doesn't work. So, I can't check my threads work correctly or not. How can I implement checkPrime function?
There are 3 functions. crossout is for Sieve E. method. checkPrime is for checking is a number prime or not. worker is for thread's function. Each thread must check one prime number.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#define MAX_N 100000000
#define MAX_THREADS 25
// global values
int threadNumber;
int largestNumber;
int isPrime;
int nthreads, // number of threads (not counting main())
prime[MAX_N + 1],
n, // in the end, prime[i] = 1 if i prime, else 0
nextbase; // next sieve multiplier to be used
// lock for the shared variable nextbase
pthread_mutex_t nextbaselock = PTHREAD_MUTEX_INITIALIZER;
void crossout(int a) {
int i, j, check;
for (i = 2; i < largestNumber; i++)
prime[i] = 1;
for (i = a; i < largestNumber;)
if (prime[i])
for (j = i; i * j < largestNumber; j++)
prime[i * j] = 0;
}
int checkPrime(int a) {
int i;
for (i = 2; i <= a; ++i) {
if (a % i == 0) {
isPrime = 1;
return isPrime;
break;
} else
isPrime = 2;
crossout(a);
return isPrime;
}
}
void* workerThread(void* t) {
int lim, base;
long i, j;
long tid;
tid = (long)t;
printf("Thread %ld starting...\n", tid);
while (1) {
pthread_mutex_lock(&nextbaselock);
base = nextbase;
nextbase++;
// unlock the lock
pthread_mutex_unlock(&nextbaselock);
if (base <= lim) {
if (prime[base]) {
checkPrime(base);
// log work done by this thread
}
}
if (checkPrime(base) == 2)
printf("Thread %ld done. Prime = %d\n", tid, base);
pthread_exit((void*) t);
}
return NULL;
}
//main function with two parameters :argc and argv
int main(int argc, char** argv) {
threadNumber = argv[3];
largestNumber = argv[1];
int i;
pthread_t thread[threadNumber];
int rc;
long t;
void* status;
for (t = 0; t < threadNumber; t++) {
printf("Main: creating thread %ld\n", t);
rc = pthread_create(&thread[t], NULL, workerThread, (void*)t);
if (rc) {
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
for (t = 0; t < threadNumber; t++) {
rc = pthread_join(thread[t], (void*)&t);
if (rc) {
printf("ERROR; return code from pthread_join() is %d\n", rc);
exit(-1);
}
printf("Main: completed join with thread %ld \n", t);
}
}
You are trying to mix two different methods for finding prime numbers. You don't need to use both the iterative division method and the sieve of Eratosthenes. This shows a way of implementing the sieve. Even numbers are ignored in the sieve but treated as special cases in isprime(). But it won't help you find a multi threaded solution, because you can't just hand over different numbers to different threads - each prime builds on the work of the previous prime, starting with the assumption that 3 is prime.
// Sieve of Eratosthenes
#include <stdio.h>
#include <stdlib.h>
#define LIMIT 200
char sieve[LIMIT] = { 1, 1, }; // 1 for not-prime
int isprime(unsigned n)
{
if(n <= 2) // special cases
return sieve[n] == 0;
if(n % 2 == 0) // even numbers are not prime
return 0;
if(n >= LIMIT) // test range
exit(1);
return sieve[n] == 0;
}
int main(void)
{
unsigned n, p;
for(n=3; n<LIMIT; n+=2) { // odd numbers only
if (sieve[n] == 0) { // if n is prime
for(p=n*n; p<LIMIT; p+=n*2) { // ignore even numbers
sieve[p] = 1; // not primne
}
}
}
printf("Prime numbers are:\n");
for(n=0; n<LIMIT; n++) { // check all numbers
if (isprime(n)) { // if n is prime
printf("%-4d", n);
}
}
printf("\n");
return 0;
}
Program output:
Prime numbers are:
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71
73 79 83 89 97 101 103 107 109 113 127 131 137 139 149 151 157 163 167 173
179 181 191 193 197 199
I'll now show an iterative division method. Once again, even numbers are treated as special cases. I don't often write multi threaded C code, so I can't help you with that. But I hope you can build on this second example to make a multi threaded solution.
// iterative division
#include <stdio.h>
#include <math.h>
#define LIMIT 200
int isprime(unsigned n)
{
unsigned s, i;
if(n <= 1)
return 0;
if(n == 2)
return 1;
if(n % 2 == 0) // no even numbers
return 0;
s = (unsigned)sqrt(n); // limit the loop
for(i=3; i<=s; i+=2) // odd numbers only
if (n % i == 0)
return 0;
return 1;
}
int main(void)
{
unsigned n;
printf("Prime numbers are:\n");
for(n=0; n<LIMIT; n++) { // check all numbers
if (isprime(n)) { // if n is prime
printf("%-4d", n);
}
}
printf("\n");
return 0;
}
Program output:
Prime numbers are:
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71
73 79 83 89 97 101 103 107 109 113 127 131 137 139 149 151 157 163 167 173
179 181 191 193 197 199
There are some pitfalls in both of the above examples when working with larger numbers, but I'll leave them for you to discover.
This is modified version of Sieve of Eratosthenes which is the very simple, interesting and fast. Understand its working as I have tried to explain it using comments. Actually try to understand the run-time allocation of array size to avoid defining a large MAX value and try to code simple by analyzing your algorithm and applying good mathematics along with smart coding knowledge.
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
int main()
{
int *arr;
int count=0,i=3,j,n;
arr=(int*)malloc(count+1*sizeof(int)); //set array size to 1
arr[count++]=2; //stored 2 as array first element
printf("Find all prime numbers upto :: ");
scanf("%d",&n); //n is the number up to which prime numbers are required
here:
{
while(i<=n) //start with i=3
{
j=0;
while(arr[j]<=sqrt(i)) //till array element value is less than or equal to root of number under checking
{
if(i%arr[j]!=0) //if remainder is not zero check divisibility with next array element
j++;
else
{
i++; //if remainder is zero then start checking for another number
goto here;
}
}
printf("%d, ",arr[count-1]); //printing the number which was proved as prime last time
arr=(int *)realloc(arr,(count+1)*sizeof(int)); //increasing array size by 1
arr[count++]=i; //newly proved prime is stored as next array element
i++;
}
printf("%d, ",arr[count-1]); //print last number proved as prime
}

Copying dynamically one array of structures to another array of structures in C

I have to copy the elements of one array of structure to blank elements of a new array of structures (all dynamically allocated). Every element of the array of structures I have, structure 'a', has only two columns, left_column and right_column. Some of the right column entries of each element of structure a (say, i'th structure element) matches the left column entry of the next (viz., i+1 th) structure element of the same structure a. I am attempting to find such matching entries and I am attempting to copy the entire left and right column of the matching elements one-by-one to a smaller, conserved structure, structure b. The problem is the code is compiling, but it is not getting into the all-important matching part, viz., the if part. It is getting into the while loop.
Kept below are the information and sample data. This code has come to this stage due to 'PlerumCodeExperientia', I thank him. Please suggest how to copy these matching elements.
Thanking you, Dan.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* args[])
{
struct a
{
int left_line;
int right_line;
};
struct b
{
int conserved_left;
int conserved_right;
};
FILE *fp100; // Output File
fp100 = fopen("Conserved_Elements.txt", "a");
struct a *ptr1;
int structACapacity = 3; // Only 3 such comparison files are being worked with, there are >1000 comparison files
ptr1 = malloc(structACapacity*sizeof(struct a));
struct b *ptr2;
int structBCapacity = 1000;
ptr2 = malloc(structBCapacity*sizeof(struct b));
int structure_ctr;
int number_of_line_comparison_files = 3; // Only 3 for the time being
int knt;
int left, right;
for (structure_ctr=0; structure_ctr < number_of_line_comparison_files; structure_ctr++) {
knt = 0;
while (((ptr1+knt) < (ptr1+structACapacity-1)) && (knt < 500)) {
fprintf(fp100, "Getting Into While\n");
// finding the matching entries between right column of knt and left column of (knt+1)
if ((ptr1+knt)->right_line == (ptr1+(1+knt))->left_line) {
fprintf(fp100,"\tGetting Into the If\n");
// copying matching values to the struct b
left = (ptr2+knt)->conserved_left = (ptr1+knt)->left_line;
right = (ptr2+knt)->conserved_right = (ptr1+knt)->right_line;
//fprintf(fp100,"C-Left:%d\tC-Right:%d\tLeft%d\tRight%d\n",(ptr2+knt)->conserved_left,(ptr2+knt)->conserved_right,left,right);
// left, right are there for convinience only - easier to see, same values
fprintf(fp100,"C-Left:%d\tC-Right:%d\n", left,right);
}
++knt;
} // end of while
} //end of for
}
The files look:
A fragment of the first structure element looks like:
17 216
26 119
28 16
29 122
59 124
60 116
62 114
63 112
66 61
69 54
70 51
71 62
91 40
99 38
A fragment of the Second element looks like:
321 25
110 45
116 49
216 110
56 117
54 131
32 167
31 178
8 188
12 199
39 239
60 244
121 263
124 275
A fragment of the 3rd element looks like:
75 223
61 248
45 278
31 290
10 291
111 311
117 324
128 338
139 347
148 365
167 376
178 381
191 394
193 397
etc..., there are many such elements. All of them contain such unformatted two columns of integers.
In case if you are interested to see how the content of the original file was loaded into 'structure_a', the next piece is given. It works fine.
for(q=0; q < number_of_line_comparison_files; q++) // going through the total number of files
{
// File Name Etc ..
while (fgets(file_line,99,line_comparison_file)!= NULL)
{
++number_of_lines ; // Integer
for(j=0;j<6;j++)
string_left_line[j]=file_line[j];
for(j=0;j<6;j++)
string_right_line[j]=file_line[6+j];
left_line = atoi(string_left_line);
right_line = atoi(string_right_line);
*(&(ptr1+q)->left_line) = left_line;
*(&(ptr1+q)->right_line) = right_line;
fprintf(fp100,"Left:%d\tRight:%d\n",(ptr1+q)->left_line,(ptr1+q)->right_line);
} // END OF THE 'WHILE'
fprintf(fp100,"\n\n\t================================== ================================\n\n");
} // End of For
Dan
I must say that, there should be a little more information, for the question to be completely clear.
With the given data, this is my answer. At least the part of what I assume is asked.
I hope it helps.
// copy_pointer_struct.c
#include<stdio.h>
#include<stdlib.h>
int main(int argc, char* args[])
{
struct a
{
int left_line;
int right_line;
};
struct b
{
int conserved_left;
int conserved_right;
};
FILE *fp100;
fp100 = fopen("struct_file.txt", "a");
struct a* ptr1;
int structACapacity = 3;
ptr1=(struct a*)malloc(structACapacity*sizeof(struct a));
struct b *ptr2;
int structBCapacity = 1000;
ptr2=(struct b*)malloc(structBCapacity*sizeof(struct b));
// for writing test values to ptr1 array
int i;
for ( i = 0; i < structACapacity; i++ )
{
ptr1[i].left_line = i;
(ptr1+i)->right_line = i+1;
}
int structure_ctr,
number_of_line_comparison_files = 10,
knt;
// This outer for is neccessary only if you are getting structs form another source - a file for example or another structure.
//for(structure_ctr=0; structure_ctr < number_of_line_comparison_files; structure_ctr++)
{
// this inner for would be neccessary if you had an 2 dimensional array of structs or a pointer to a pointer to struct.
//for(knt=0; knt<500; knt++)
{
knt = 0;
// in your while condition there is no changing value, (change being made inside cycle or condition itself),
// which results in an infinite (for condition true) cycle or 0 cycles (for condition false)
// this particular condition works until we have reached 500th element or the end of array,
// whichever has lower value.
// Of course in case of use of outer for ( && knt < 500) wouldn't be used, depending of the goal you have.
while( (ptr1+knt) < (ptr1+structACapacity-1) && knt < 500 )
{
if( (ptr1+knt)->right_line == (ptr1+1+knt)->left_line ) // comment line for file test
{
// copying duplicate values to the struct b
int left = (ptr2+knt)->conserved_left = (ptr1+1+knt)->left_line;
int right = (ptr2+knt)->conserved_right = (ptr1+knt)->right_line;
// here you can write those values to a file as 2 integers, for example
fprintf(fp100,"%d %d\n", left, right);
}
++knt;
} // while
}//
} //for structure_ctr
fclose(fp100);
}
Perhaps this addition helps:
// copy_pointer_struct.c
#include<stdio.h>
#include<stdlib.h>
typedef struct a
{
int left_line;
int right_line;
} structA;
typedef struct b
{
int conserved_left;
int conserved_right;
} structB;
int fillColumnPtr(FILE* source, structA* ptr);
int main(int argc, char* args[])
{
FILE *fp100;
fp100 = fopen("struct_file.txt", "w");
structA* ptr1;
int structACapacity = 1000;
ptr1=(structA*)malloc(structACapacity*sizeof(struct a));
printf("kapacitet ptr1: %d\n", sizeof ptr1);
structB *ptr2;
int structBCapacity = 1000;
ptr2=(struct b*)malloc(structBCapacity*sizeof(struct b));
char *filename = "columns_file4.txt";
FILE *cfile1 = fopen(filename, "r");
printf("Loading values from file: %s . . . \n", filename);
int number_of_lines = fillColumnPtr(cfile1, ptr1);
fclose(cfile1);
printf("Done.\n\n");
printf("Values loaded to ptr1(total lines %d):\n", number_of_lines);
int i;
for ( i = 0; i < number_of_lines; i++ )
{
printf("left: %6d, right: %6d\n", ptr1[i].left_line, ptr1[i].right_line);
}
printf("\nProcessing...\n");
int structure_ctr,
number_of_line_comparison_files = 10,
knt;
knt = 0;
while( (ptr1+knt) < (ptr1+structACapacity-1) && knt < number_of_lines )
{
if( (ptr1+knt)->right_line == (ptr1+1+knt)->left_line ) // comment line for file test
{
// copying duplicate values to the struct b
int left = (ptr2+knt)->conserved_left = (ptr1+1+knt)->left_line;
int right = (ptr2+knt)->conserved_right = (ptr1+knt)->right_line;
// here you can write those values to a file as 2 integers, for example
fprintf(fp100,"%d %d\n", left, right);
printf("%d %d\n", left, right);
}
++knt;
} // while
fclose(fp100);
}
// function: transfers data from a source file to pointer to struct
int fillColumnPtr(FILE* source, structA* ptr)
{
char file_line[20],
*str_left_line = calloc(sizeof(char), 6),
str_right_line[6];
int left_line, right_line, j, line_counter = 0, i = 0;
while ( fgets(file_line, 19, source) != NULL )
{
printf(">> fileline: %s", file_line);
for(j=0;j<6;j++)
{
str_left_line[j]=file_line[j];
str_right_line[j]=file_line[6+j];
}
left_line = atoi(str_left_line);
right_line = atoi(str_right_line);
printf(" left right: %-3d %6d\n", left_line, right_line);
ptr[i].left_line = left_line;
ptr[i].right_line = right_line;
++i;
++line_counter;
}
return line_counter;
}
Note: I examined few of your source values, that are supposed to be in a file - non of them satisfies the condition inside if, resulting in an empty pointer.
The additional posted, I have tested with altered values and it works.
For this method check the spacing in rows.
Contents of the "columns_file4.txt":
321 25
25 45
116 49
216 110
110 117
54 131
32 167
31 178
178 188
12 199
199 239
60 244
121 263
124 275
// End of file
In this file there are equal values for example:
(row 1 col right)25 == (row 2 col left )25, 110 , 178, 199.
If this is not what you are looking for, then alter the if condition.
Good luck.
Hope this help.

Resources