DE_CR DE_CR -4 years ago 130
C Question

How do I replace sequential operation with pthreads in C?

I have a function which is calculating number sub-strings of one bigger string (using a smaller string to match), I am trying to replace this sequence with pthreads, thereby processing the whole thing at the same time without a loop.

I am looking for the principle by which i can do this.
What i've done so far, is creating a pthread_t dynamic array, the number of this array is the same as the number of the chars. of the bigger string, I am assigning the function that calculates sub strings to the threads, I think I almost gut it, I just need a push forward to get it right.

pthreads.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>


#define MAX 1024

int total = 0;
int n1,n2;
int num_thr;
int *num_threads;
char *s1,*s2;
FILE *fp;

int readf(FILE *fp)
{
if((fp=fopen("strings.txt", "r"))==NULL){
printf("ERROR: can't open string.txt!\n");
return 0;
}
s1=(char *)malloc(sizeof(char)*MAX);
if(s1==NULL){
printf("ERROR: Out of memory!\n");
return -1;
}
s2=(char *)malloc(sizeof(char)*MAX);
if(s1==NULL){
printf("ERROR: Out of memory\n");
return -1;
}
/*read s1 s2 from the file*/
s1=fgets(s1, MAX, fp);
s2=fgets(s2, MAX, fp);
n1=strlen(s1)-1; /*length of s1*/

n2=strlen(s2)-1; /*length of s2*/
num_thr=n1;
printf("String 1 len = %d\n",n1);

if(s1==NULL || s2==NULL || n1<n2) /*when error exit*/
return -1;
}

void *num_substring(void *vari);
void *num_substring(void *vari)
{
int i,j,k;
int count;

for (i = 0; i <= (n1-n2); i++){
count=0;
for(j = i,k = 0; k < n2; j++,k++){ /*search for the next string of size of n2*/
if (*(s1+j)!=*(s2+k)){
break;
}
else
count++;
if(count==n2)
total++; /*find a substring in this step*/
}
}
printf("total= %d\n",total);
//return total;
}








int main (int argc, char *argv[])
{

int count;

readf(fp);

printf("The number of substrings is: %d\n", count);



int i, ret=-1;
char *msg1= "a thread";
pthread_t * thread_arr = malloc(sizeof(pthread_t)*num_thr);
printf("num threads inside main = %d\n",num_thr);
for (i = 0; i < num_thr; i++) {

ret = pthread_create(&thread_arr[i], NULL, num_substring, (void *) msg1);

if(ret != 0) {
printf ("Create pthread %d error!\n",i);
exit (1);
}
printf("Main function thread %d created\n",i);
}

for (i=0;i < num_thr; i++){
pthread_join(thread_arr[i], NULL);
}




return 0;
}


The correct output of this program must be 4, because
ab
occurs 4 times in the other string, so number of sub-string must equal 4 :

string.txt content :

abcdabsufsoababuosufba

ab

My Output is not completely false because it displays 4 initially then it starts incrementing (which is not what i want all i want is the 4) but, it's still not complete because I have not replaced the loops with pthreads array (pthread_arr) which is iam guessing is the last step needed, here is my output :

String 1 len = 22
The number of substrings is: 10219508
num threads inside main = 22
Main function thread 0 created
Main function thread 1 created
Main function thread 2 created
Main function thread 3 created
total= 4 // this is the correct number of substrings
total= 8
total= 12
Main function thread 4 created
total= 20
total= 16
Main function thread 5 created
Main function thread 6 created
total= 24
Main function thread 7 created
total= 28
Main function thread 8 created
total= 36
total= 32
Main function thread 9 created
total= 40
Main function thread 10 created
total= 44
Main function thread 11 created
Main function thread 12 created
total= 48
total= 52
Main function thread 13 created
total= 56
Main function thread 14 created
total= 60
Main function thread 15 created
Main function thread 16 created
Main function thread 17 created
Main function thread 18 created
Main function thread 19 created
Main function thread 20 created
Main function thread 21 created
total= 64
total= 68
total= 84
total= 76
total= 72
total= 80
total= 88

Answer Source

You were pretty close, but there were some bugs.

  1. Each thread was scanning the entire s1 instead of just a substring.
  2. main should pass an argument that indicates the starting offset of the substring in s1
  3. Only one loop in the thread function is required [or desired].
  4. Each thread was incrementing a global total [without thread locking]. Better to have the value passed back as the thread's return value
  5. Because you have one thread for each char in s1, a thread will see either 0 or 1 as the count [only].

I've fixed your code [please pardon the gratuitous style cleanup]:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>

#define MAX 1024

int n1;
int n2;
int num_thr;
int *num_threads;
char *s1;
char *s2;
FILE *fp;

int
readf(FILE * fp)
{
    char *cp;

    if ((fp = fopen("strings.txt", "r")) == NULL) {
        printf("ERROR: can't open string.txt!\n");
        return 0;
    }

    if (s1 == NULL)
        s1 = (char *) malloc(sizeof(char) * MAX);
    if (s1 == NULL) {
        printf("ERROR: Out of memory!\n");
        return -1;
    }

    if (s2 == NULL)
        s2 = (char *) malloc(sizeof(char) * MAX);
    if (s1 == NULL) {
        printf("ERROR: Out of memory\n");
        return -1;
    }

    /* read s1 s2 from the file */
    cp = fgets(s1, MAX, fp);
    if (cp == NULL)
        return -1;

    cp = fgets(s2, MAX, fp);
    if (cp == NULL)
        return -1;

    n1 = strlen(s1) - 1;                /* length of s1 */
    n2 = strlen(s2) - 1;                /* length of s2 */

    num_thr = n1;
    printf("String 1 len = %d\n", n1);

    if (n1 < n2)
        return -1;

    return 0;
}

void *
num_substring(void *vari)
{
    int i;
    long subtotal;

    subtotal = 0;

#if 0
    int count;
    int j;
    int k;
    for (int i = 0; i <= (n1 - n2); i++) {
        count = 0;
        /* search for the next string of size of n2 */
        for (int j = i, k = 0; k < n2; j++, k++) {
            if (*(s1 + j) != *(s2 + k)) {
                break;
            }
            else
                count++;
            if (count == n2)
                subtotal++;             /* find a substring in this step */
        }
    }
#else
    int t = (long) vari;
    char *cp = &s1[t];
    subtotal = 1;
    for (i = 0; i < n2; i++) {
        //printf("t%d: TRY: %c %c\n",t,cp[i],s2[i]);
        if (cp[i] != s2[i]) {
            subtotal = 0;
            break;
        }
    }
#endif

    //printf("t%d: subtotal= %ld\n", subtotal);

    return (void *) subtotal;
}

int
main(int argc, char *argv[])
{
    int total = 0;
    void *ptr;

    //int count;

    readf(fp);

    //printf("The number of substrings is: %d\n", count);

    long i;
    int ret = -1;
    //char *msg1 = "a thread";
    pthread_t *thread_arr = malloc(sizeof(pthread_t) * num_thr);

    printf("num threads inside main = %d\n", num_thr);
    for (i = 0; i < num_thr; i++) {
#if 0
        ret = pthread_create(&thread_arr[i], NULL, num_substring,(void *) msg1);
#else
        ret = pthread_create(&thread_arr[i], NULL, num_substring,(void *) i);
#endif

        if (ret != 0) {
            printf("Create pthread %ld error!\n", i);
            exit(1);
        }
        printf("Main function thread %ld created\n", i);
    }

    total = 0;
    for (i = 0; i < num_thr; i++) {
        pthread_join(thread_arr[i], &ptr);
        total += (long) ptr;
    }

    printf("TOTAL: %d\n",total);

    return 0;
}
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download