Search code examples
cnode.jsopenmpreaddiropendir

How to use openmp to convert jpg2dicom?


I'm need to convert hundreds of jpg images to dicom. I have a web application where this piece was originally made with Node.js, but is very slow. I thought to do in C and use openmp to parallelize the following code:

int main(){
    DIR *dir;
    struct dirent *arq; 
    dir = opendir("./jpg");
    char cmd1[255] = "./dcm4che-2.0.23/bin/jpg2dcm -c dcm4che-2.0.23/etc/jpg2dcm/jpg2dcm.cfg jpg/";
    char cmd_aux[255] = "./dcm4che-2.0.23/bin/jpg2dcm -c dcm4che-2.0.23/etc/jpg2dcm/jpg2dcm.cfg jpg/"; 
    char buf[255];
    char nomeArq[255];
    int i;
    //Stretch in which I use openmp 
    while ((arq = readdir(dir)) != NULL){
        strncpy(nomeArq, arq->d_name, 255);
        if(nomeArq[0] != '.'){
           sprintf(buf, " dcm/imagem-%d.dcm", i); 
           strcat(cmd1, nomeArq); // cmd1 + nomeArquivo
           strcat(cmd1, buf); 
           system(cmd1); 
           strncpy(cmd1, cmd_aux, 255);
     }
      i++;
    }
    closedir(dir);
    return 0;
}

How do I know this code is I / O bound, I would like to ask if really can't get any speedup with openmp. And if is possible, how to parallelize this loop while using openmp. If I was not very clear, sorry! I'm still learning english!


Solution

  • Bash solution

    First, your task would be easier if you considered existing tools :

    Example with xargs (from your bash command prompt) :

    ls ./jpg | xargs -P 0 -i ./dcm4che-2.0.23/bin/jpg2dcm -c dcm4che-2.0.23/etc/jpg2dcm/jpg2dcm.cfg jpg/{} dcm/{}.dcm
    

    OpenMP

    It is easier to work with for loops, you could start putting the list of files into an array ( Stackoverflow code on how to do it ).

    // put your code for reading he files list into an array //
    
    int main() {
        char **files;
        const size_t count = file_list("./jpg", &files);
    
        #pragma omp parallel for
        for(size_t i=0;i<count;++i) {
            if(files[i][0] == '.' ) { continue; } // 'skip' directory entry, maybe you should implement some better check ( extension, or even checking if it is a file at all)
            // keep the buffer local to the loop
            char *buf = malloc(1024);
            // already calling sprintf, use it for building the whole command line, and avoid the strncpy & strcat
            sprintf(buf, "./dcm4che-2.0.23/bin/jpg2dcm -c dcm4che-2.0.23/etc/jpg2dcm/jpg2dcm.cfg jpg/%s dcm/imagem-%zu.dcm",files[i],i);
            system(buf);
            free(buf); // cleanup
        }
        return EXIT_SUCCESS;
    }