【问题标题】:Parallel I/O SSD vs HDD surprising resultsParallel I/O SSD vs HDD 令人惊讶的结果
【发布时间】:2013-07-14 14:47:37
【问题描述】:

我的一些关于并行 I/O 的测试发生了一个非常奇怪的情况。情况就是这样。我有多个线程打开同一个文件的文件处理程序,并从文件的多个位置(均匀间隔)读取有限数量的字节并将其转储到数组中。一切都是通过增强线程完成的。现在,我假设由于随机访问搜索,HDD 应该会变慢。这就是为什么我的测试实际上是针对 SSD 的。事实证明,与 HDD 相比,从固态磁盘读取相同文件时,我几乎没有得到任何加速。想知道问题可能是什么?这对我来说似乎很令人惊讶/我还在下面发布我的代码,看看我到底在做什么:

    void readFunctor(std::string pathToFile, size_t filePos, BYTE* buffer, size_t buffPos, size_t dataLn, boost::barrier& barier) {

        FILE* pFile;
        pFile = fopen(pathToFile.c_str(), "rb");

        fseek(pFile, filePos, SEEK_SET);
        fread(buffer, sizeof(BYTE), dataLn, pFile);

        fclose(pFile);
        barier.wait();

    }

    void joinAllThreads(std::vector<boost::shared_ptr<boost::thread> > &threads) {

        for (std::vector<boost::shared_ptr<boost::thread> >::iterator it = threads.begin(); it != threads.end(); ++it) {
            (*it).get()->join();

        }

    }

    void readDataInParallel(BYTE* buffer, std::string pathToFile, size_t lenOfData, size_t numThreads) {
        std::vector<boost::shared_ptr<boost::thread> > threads;
        boost::barrier barier(numThreads);
        size_t dataPerThread = lenOfData / numThreads;

        for (int var = 0; var < numThreads; ++var) {
            size_t filePos = var * dataPerThread;
            size_t bufferPos = var * dataPerThread;
            size_t dataLenForCurrentThread = dataPerThread;
            if (var == numThreads - 1) {
                dataLenForCurrentThread = dataLenForCurrentThread + (lenOfData % numThreads);
            }

            boost::shared_ptr<boost::thread> thread(
                    new boost::thread(readFunctor, pathToFile, filePos, buffer, bufferPos, dataLenForCurrentThread, boost::ref(barier)));
            threads.push_back(thread);

        }

        joinAllThreads(threads);

    }

现在..在我的主文件中我几乎有..:

    int start_s = clock();
    size_t sizeOfData = 2032221073;
    boost::shared_ptr<BYTE> buffer((BYTE*) malloc(sizeOfData));
    readDataInParallel(buffer.get(), "/home/zahari/Desktop/kernels_big.dat", sizeOfData, 4);
    clock_t stop_s = clock();
    printf("%f %f\n", ((double) start_s / (CLOCKS_PER_SEC)) * 1000, (stop_s / double(CLOCKS_PER_SEC)) * 1000);

令人惊讶的是,从 SSD 读取时,与 HDD 相比,我没有得到任何加速?为什么会这样?

【问题讨论】:

  • 它可能首先写入输出缓冲区?你的意思是 ?为什么它会写入输出缓冲区,即使它确实如此,这又有什么关系呢?
  • 考虑限制因素——硬盘上的文件有多碎片化?随机部分会在同一个(或附近)圆柱体上吗?峰值吞吐量是多少(与 SATA 连接的容量相比)?还有什么在使用磁盘?
  • 所有操作系统在内存中缓存文件。如果您多次运行测试,您将从内存而不是 HDD 或 SSD 中获取文件。
  • 您使用什么大小的数据文件? 1 KB、1 MB、1 GB?
  • 多个线程不能同时访问同一个驱动器。线程会争夺共享资源,这将成为主要的瓶颈。尝试将磁盘访问与互斥锁同步以获得更干净的基准。

标签: c++ c io parallel-processing solid-state-drive


【解决方案1】:

您的测量主要是设置四个线程的所有样板,每个线程执行一次读取,然后在四个线程中的最后一个执行barier.wait() 时终止。

为了衡量性能,每个线程在终止前应该循环读取数千个单字节。

以下是我的更改建议:

   void readFunctor(std::string pathToFile, size_t filePos, BYTE* buffer, size_t buffPos, size_t dataLn) 
   {

       FILE* pFile;
       pFile = fopen(pathToFile.c_str(), "rb");

       fseek(pFile, filePos, SEEK_SET);
       // initialize random number generation
       std::random_device rd;
       tr1::uniform_int_distribution<> randomizer(0, dataLn-1);

       for (int i=0; i<dataLn; i++)
       {
           fseek(pFile, filePos+randomizer(rd), SEEK_SET);
           fread(buffer++, sizeof(BYTE), 1, pFile);
       }

       fclose(pFile);
    }

【讨论】:

  • 好吧,那么您对我的代码更改有何建议。使用 fread(buffer, sizeof(BYTE), dataLn, pFile); 一次读取一千个字节有什么区别?与执行那一千次并每次读取一个字节相比?
  • 在您的代码中调用fread 会导致读取一个即使在硬盘上也表现良好的大块。并行执行单个字节的随机读取与此完全不同。我将尝试在单独的答案中发布一个想法......
  • 所以无论文件的物理布局是什么,将其置于循环理论上会降低 HDD 的性能?
  • 同样,即使在循环中,结果也是:HDD 为 44190 毫秒,SSD 为 44760 毫秒。奇怪,你不觉得吗?
  • 你在哪个平台上运行它?您为编译器使用的优化级别是什么?
【解决方案2】:

根据您的数据大小,无论是 SSD 还是 HDD,操作系统都会缓存您的文件。所以,你可能不是真的在访问你的磁盘,而是内存。

【讨论】:

  • 有没有办法强制这种情况不发生?
  • 我不确定。无论如何,这应该取决于操作系统。
  • 我通常将我的测试大小设置为内存大小的 2 到 4 倍。或者在 linux 上告诉操作系统删除缓存。您通常还可以告诉操作系统使用直接 io 或无缓冲读写。
  • @drescherjm 抱歉我的无知,但是你如何告诉操作系统“删除缓存”?
  • 是否使用int setvbuf(FILE *stream, char *buf, int mode, size_t size);
【解决方案3】:

您的文件可能会被缓存,因此您测量的是 CPU 开销而不是 I/O。您可以在读取文件之前调用posix_fadvise(),而不是刷新整个磁盘缓存,并使用“wontneed”标志建议内核不要缓存它。也就是说,假设您使用的是某种 *nix 平台或 Mac OS。

【讨论】:

    【解决方案4】:

    对此的可能解释是您没有在 SATA III 设置下运行。您正在使用的 SATA III 6gb/s SSD 驱动器连接到主板上较旧的 SATA II 3gb/s 控制器。在这种情况下,您的 SSD 会被限制为 3 gb/s。

    检查您的硬件配置。如果是 SATA II,则需要更换主板才能让您的 SSD 发挥其全部性能潜力。

    同时检查您的 HDD 磁盘驱动器是否为 SATA、SATA II 或 SATA III。

    确保您在硬件接口级别比较苹果和苹果。

    【讨论】:

      猜你喜欢
      • 2018-01-09
      • 2022-06-11
      • 2013-06-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-05
      相关资源
      最近更新 更多