Search code examples
cmultithreadingparallel-processingopenmp

C - invalid branch to/from OpenMP structured block


I have a code in c that counts the numbers of occurrences of specific words but I want to do it with openmp.

Which word is a char and its defined in main()

When I try to compile it I get the following error:

In function ‘wordCount’: error: invalid branch to/from OpenMP structured block

I tried to search this same error, but I'm not being able to fix it, I'm very newbie in openmp and especially in c.

Here's the whole code:

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <sys/time.h>
    #include <omp.h>
    
    struct timeval t1, t2;
    
    void execTime(){
      double t_total = (t2.tv_sec - t1.tv_sec) + ((t2.tv_usec - t1.tv_usec)/1000000.0);
      printf("\n");
      printf("\n");
      printf("Total Time = %f\n", t_total);
      printf("\n");
    }
    
    int wordCount(char* file_path, char* word){
        FILE *fp;
        int count = 0;
        int ch, len;
    
        if(NULL==(fp=fopen(file_path, "r")))
            return -1;
        len = strlen(word);
        for(;;){
            int i;
            if(EOF==(ch=fgetc(fp))) break;
            if((char)ch != *word) continue;
            
           omp_set_num_threads(4);
    
           #pragma omp parallel for  
            for(i=1;i < len;++i){
                if(EOF==(ch = fgetc(fp))) 
                    goto end;
                if((char)ch != word[i]){
                    fseek(fp, 1-i, SEEK_CUR);
                    goto next;
                }
            }
            ++count;
            next: ;
        }
        end:
            fclose(fp);
            return count;
    }
    
    int main()
    {
        char word1[] = "hello";
        char word2[] = "libero";
        char word3[] = "egestas";
        char word4[] = "vestibulum";
    
        int wordcount1 = 0;
        int wordcount2 = 0;
        int wordcount3 = 0;
        int wordcount4 = 0;
    
        gettimeofday(&t1, NULL);
      
        wordcount1 = wordCount("file.txt", word1);
        wordcount2 = wordCount("file.txt", word2);
        wordcount3 = wordCount("file.txt", word3);
        wordcount4 = wordCount("file.txt", word4);
        gettimeofday(&t2, NULL);
    
        printf("Word hello occurs %d times\n",wordcount1);
        printf("Word libero occurs %d times\n",wordcount2);
        printf("Word egestas occurs %d times\n",wordcount3);
        printf("Word vestibulum occurs %d times\n",wordcount4);
        execTime();
        return 0;
    }

Solution

  • You cannot have in OpenMP goto statement inside a parallel for:

       #pragma omp parallel for  
        for(i=1;i < len;++i){
            if(EOF==(ch = fgetc(fp))) 
                goto end; // <-- the problem
            if((char)ch != word[i]){
                fseek(fp, 1-i, SEEK_CUR);
                goto next; // <-- the problem
            }
        }
    

    And the same applies to the break statement, from the OpenMP 5.1 standard one can read:

    final-loop-body must not contain any break statement that would cause the termination of the innermost loop.

    You can try to have a look the OpenMP cancellation point feature:

    Summary

    The cancellation point construct introduces a user-defined cancellation point at which implicit or explicit tasks check if cancellation of the innermost enclosing region of the type specified has been activated. The cancellation point construct is a stand-alone directive.


    In your case, however, even if the goto was not an issue your code is not efficiently parallelizable as it is. For instance, the fgetc

    Note: This function is not thread safe, because it shares a return buffer across all threads, and many other functions in this library. const char *explain_errno_fgets(int errnum, char *data, int data_size, FILE *fp);

    Is not thread safe, which mean that you would have to ensure mutual exclusion on its accesses, which would make your code basically sequential anyway. Typically is not recommended to read the same file in parallel anyway.