超大文本文件单词频数统计

一、实验目的:

调用线程进行超大文本文件单词频数统计,测试并讨论不同线程数对代码耗时的影响

二、实验环境:

(1)c/c++,编辑器:Visual Studio与code:blocks;(2)python,编辑器:pycharm

三、实验说明:

通过在pycharm上编写代码(makefile.py)生成1G大小的单词文件(small_file)并生成各单词的数量文件(result.txt),再编写c++代码不同数目的线程统计单词数量的耗时并与result.txt进行对比判断结果是否正确。

四、实验代码:

见cod文件夹

五、实验步骤

(1)编写.py文件

①定义词典与计数器,单词文件里的单词即词典中的单词,计数器统计各单词数量

# 词典
dictionary = ['one ', 'two ', 'three ', 'four ', 'five ', 'big ', 'small ', 'light ']
# 计数器
counter = [0 for i in range(len(dictionary))]

②定义build_file函数,生成1G大小的单词文件

def build_file(file_name):
    file = open(file_name, 'w')
    file_size = os.path.getsize(file_name)
    if file_size <= oneG :
        # 文件大小小于1G
       
while file_size <= oneG:
            file.writelines(getWords())
            file_size = os.path.getsize(file_name)

③定义getWords()函数,统计各单词数量

def getWords():
    list = []
    for i in range(random.randint(1, 2)):
        index = random.randint(0, len(dictionary) - 1)
        counter[index] += 1
       
list.append(dictionary[index])
    list.append('\n')
    return list

(2)编写.cpp文件

①定义多线程共享变量dirc_loop和互斥量m

std::vector<std::map<std::string, int>> dirc_loop;

std::mutex m;

定义getFileSize函数,获得单词文件大小

int getFileSize(std::string file)

{

   if (file.empty())

      return 0;

   struct stat filestat;

   if (stat(file.c_str(), &filestat) < 0) {

      perror("error: ");

   }

   return filestat.st_size;

}

定义fileExist函数,判断单词文件是否存在

int fileExist(std::string file)

{

   if (file.empty())

      return 0;

   struct stat filestat;

   if (stat(file.c_str(), &filestat) < 0) {

      perror("error: ");

      return 0;

   }

   printf("file exist\n");

   return 1;

}

④定义readFile函数,统计各单词数量

int readFile(std::string fileName, size_t file_offsize, size_t end)

{

   std::map<std::string, int> dirc;

   std::fstream file;

   file.open(fileName, std::ios::in);

   if (!file.is_open())

      return -1;

   // 设置文件指针位置

   file.seekg(file_offsize, std::ios::beg);

   // 查找新的完整单词开始位置

   if (file_offsize != 0) {

      int last_c = file.seekg(-1, std::ios::cur).get();

      if (last_c != ' ' && last_c != '\n') {

          while (true) {

             int c = file.get();

             if (c == ' ' || c == '\n')

                break;

          }

      }

   }

   printf("read start\n");

   // 开始读取

   std::string line;

   while (file >> line) {

      if (dirc.find(line) != dirc.end())

          dirc[line] += 1;

      else

          dirc[line] = 1;

      size_t endPos = file.tellg();

      if (endPos + 1 >= end)

          break;

   }

   m.lock();

   dirc_loop.push_back(dirc);

   m.unlock();

   return 0;

}

⑤主函数

int main()

{

   printf("start\n");

   std::fstream file;

   std::string fileName = "D:\\PyCharm\\workspace\\Project\\计操\\small_file"; // 文件名

   if (!fileExist(fileName))

      return 0;

   printf("file size: %d\n", getFileSize(fileName));

   int parts = 4;   //设置线程数

   int dater = getFileSize(fileName) / parts;

   std::vector<std::thread> t_loop;

   auto start_time = std::chrono::system_clock::now();

   for (int i = 0; i < parts; i++) t_loop.push_back(std::thread(readFile, fileName, i * dater, (i + 1) * dater));

   for (int i = 0; i < parts; i++) t_loop[i].join();

   std::cout << "SPENT TIME: " << std::chrono::duration_cast<std::chrono::microseconds>((std::chrono::system_clock::now() - start_time)).count() << " 微秒" << std::endl;

   printf("read over\n");

   // 汇总结果

   for (int i = 0; i < dirc_loop.size(); i++)

   {

      if (i == 0) continue;

      for (auto d : dirc_loop[i]) {

          if (dirc_loop[0].find(d.first) != dirc_loop[0].end()) {

             dirc_loop[0][d.first] += d.second;

          }

          else {

             dirc_loop[0][d.first] = d.second;

          }

      }

   }

   // 输出

   for (auto i : dirc_loop[0])

   {

      printf("%s %d\n", i.first.c_str(), i.second);

   }

}

六、结果分析

 

由此图可以看出,随线程数的增加,程序耗时先减少后增加且不同编译器的耗时相差较大。线程多了可以提高程序并行执行的速度,但是并不是越多越好,其中,每个线程都要占用内存,多线程就意味着更多的内存资源被占用,其二,如果线程太多,cpu必须不断的在各个线程间快回更换执行,线程间的切换无意间消耗了许多时间,所以cpu有效利用率反而是下降的。并且不同的编译器对由源文件经编译生成目标文件,然后经过连接生成可执行文件的优化各不相同,故不同编译器的相同程序耗时不同。最后由于异步性,相同代码的每次执行耗时也略有差异。

  • 16
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

weixin_53774586

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值