扩展这个函数可以并行读取文件吗?

问题描述 投票:0回答:1

我用 C 语言开发了这个函数来读取每行一个单词组成的文件,就像标准的单词列表一样。 该功能已经得到了合理的优化,但我想知道是否有办法使用 OpenMP 并行化文件读取过程。我尝试了各种方法,但找不到可行的解决方案。

我的想法是在线程之间划分任务,以便每个线程使用一个私有数组来存储它读取的单词,然后将这些单词并行合并到输出数组(在主函数中使用)中。然而,我未能成功实施这种方法。 我的问题有可能的解决方案吗? 这是该函数的代码:

    int file_read(const char *filename, unsigned char (*output)[MAX_WORD_LENGTH]) {
            int fd = open(filename , O_RDONLY);
            if ( fd < 0 ){
                printf("Errore nella lettura del file\n");
                perror("fd < 0");
                exit(1);
            }
            // dimensione  file in byte
            off_t file_size = lseek(fd, 0, SEEK_END);
            lseek(fd, 0, SEEK_SET);

            // Mappiamo il file in memoria
            char *file_data = (char *) mmap(NULL, file_size, PROT_READ, MAP_PRIVATE, fd, 0);
            //mmap funzione che permette di mappare in memoria il file
            //NULL significa che decide l'os dove metterlo
            //file_size quanto è grande, calcolato prima con lseek
            //PROT_READ dice che il file è solo in lettura
            //MAP_PRIVATE privata al processo, alternativamente MAP_SHARED
            //fd file descriptor
            //0 dove iniziare a leggere il file, 0 = inizio
            if (file_data == MAP_FAILED) {
                perror("Errore nella mappatura del file");
                close(fd);
                exit(1);
            }

            close(fd);

            int num_words = 0;
            int i=0, temp_len=0;
            char tempChar;
            while ( i < file_size && num_words < MAX_WORDS ){
                tempChar = file_data[i];
                if(tempChar=='\n'){
                    if(temp_len <= MAX_WORD_LENGTH){
                        if(temp_len > 0){
                            output[num_words][temp_len]='\0';
                            temp_len = 0;
                            num_words++;
                        }
                    }
                    else{
                        printf("Parola troppo grande");
                        exit(1);
                    }
                }
                else if(tempChar!='\r'){
                    output[num_words][temp_len++]=tempChar;
                }
                i++;
            }

            //rilascio la memoria su cui era inserito il file
            munmap(file_data, file_size);

            return num_words;

        }

附注该代码旨在读取大量数据,例如一百万个单词,在我的例子中,单词的最大长度为 56。 谢谢。

c file optimization parallel-processing openmp
1个回答
0
投票

如果我正确理解你的问题,你想并行化从文件中读取单词的过程。

虽然并行执行多个文件很简单,但我将重点关注并行读取单个文件。

我建议将问题分为两个阶段:

  1. 获取有效Chunk(单线程/主线程)

    • 确定文件大小,并根据您要使用的固定数量的线程或您可以在线程完成时动态分配的更高数量将其分成更小的块。
    • 划分之后,找到从每个块的边界开始的第一个空格字符。这将是线程
      i
      的终点和线程
      i+1
      的起点。
  2. 重写While循环(多线程)

    • 将while循环转换为可以被线程调用的函数。该函数应将内存映射文件区域、起始查找和结束查找作为输入。
    • 请注意,每个文件描述符的查找都是唯一的,因此为每个线程创建多个文件描述符可能是明智的。使用您的算法并返回单词列表。

此外,我建议使用树结构,例如AVL-Tree,其中线程可以直接插入到目标结构中,合理的访问时间为 O(log(n))。您可以使用单词作为键,使用出现次数作为值。如果该单词已经存在,只需添加计数即可;否则,创建一个新节点。

为了提高效率,我建议使用互斥体来修改树,以便线程一次写入一个。如果您有足够的 RAM,为每个节点创建一个互斥锁以及值可能会很有趣,从而允许并行插入而不降低性能。这可能会创建具有相同密钥的多个节点,但您可以在算法结束时通过遍历所有节点 (O(n)) 并对内容求和来合并它们。

如果您喜欢简单的列表/数组,请再次遍历树并将节点线性化为列表/数组(可能删除互斥体)。

我希望这能给你一个好主意!

© www.soinside.com 2019 - 2024. All rights reserved.