【问题标题】:Java write to file using multi-threading doesn't speedup executionJava 使用多线程写入文件不会加速执行
【发布时间】:2012-08-01 17:34:53
【问题描述】:

前段时间我曾向this question 询问过如何加快将图像写入文件的速度。我基本上有一个 OpenGL 应用程序。在每个渲染循环结束时,我将帧缓冲区保存到图像文件中。

   fbo.readFrame();

   glReadPixels(0, 0, _viewportWidth, _viewportHeight, GL_RGBA, GL_UNSIGNED_BYTE, _data);
   _data.rewind(); //ByteBuffer
   new TImageExporter(ImageExporter.TGA, "renderings/", _data, _viewportWidth, _viewportHeight, true, _frameCount++).run();

TImageExporter 扩展了 Thread 并在“run()”方法中执行写入文件。 令我惊讶的是,50 帧的渲染循环所用的时间几乎与我使用图像导出器的单线程版本一样。 (3293 毫秒 - 多线程和 3437 毫秒使用单线程)。我在这里做错了什么? 那就是TImageExporter里面的代码:

public void export() {
    _pixels = new int[_width * _height];
    int bindex;
    int plenght = _pixels.length;
    // convert RGB data in ByteBuffer to integer array
    for (int i = 0; i < plenght; ++i) {
        bindex = i * 4;  //use 3 for RGB
          //// here write the pixels to RGBA/////
         ............
         .......................

    }

    _image.flush();
    _image.setRGB(0, 0, _width, _height, _pixels, 0, _width);
    _image = ImageUtils.flipY(_image);

    renderByFormatType();

}

private void renderByFormatType() {


    String formattedString = String.format(_formatString, _frameCount);

    if (_exportType.equals(TGA)) {
        try {
           writeTGA(_image, new File(_renderPath + "screenshot_test" + formattedString + ".tga"), _flipX);
        } catch (IOException ex) {
            Logger.getLogger(TImageExporter.class.getName()).log(Level.SEVERE, null, ex);
        }
    }




}

@Override
public void run() {


        export();



}

更新: 人们在这里问我是否写入同一个文件。不,每个线程都写入一个全新的文件。

更新1: 设置一个全局静态变量,其中包含 BufferedImage 数组。现在每个新的 TImageExporter 将图像数据写入该数组到不同的索引。直接写入磁盘时,我得到的只是 3038 毫秒而不是 3437。

【问题讨论】:

  • 在将 _data ByteBuffer 传递给线程之前,你会复制它吗?
  • 另外,您是否通过分析器运行代码以查看瓶颈在哪里?
  • @jtahlborn,是的,我复制了它。

标签: java multithreading opengl


【解决方案1】:

多线程不会加速文件传输,因为:

  1. 进行非线程安全文件写入将覆盖其他线程在 1 个线程进行保存时正在写入的一些信息 它。

  2. 磁盘 I/O 是您的瓶颈。最好的办法是将你想要的内容写入内存流(有人编辑并提供文档我 不能很快找到它)并允许它写入磁盘..这个 将允许恒定的磁盘 i/o 而无需担心线程

【讨论】:

  • 所以你说我最好将它写入 ByteBuffers 并在渲染结束时将它们保存到文件中。如果我有 10000 帧要写入?它会炸毁内存吗?我可以有一个静态或全局数组来保存在 TImageWriter 内的每个线程中创建的 BufferedImage 实例吗?
  • 是的,它会炸毁内存。记住你的约束 Int 是 4 字节,char 是 2 字节。一次写入磁盘的次数越多越好。如果需要,可以制作一个生成随机 int 的程序,并将其保存到文件中。数一数,看看它在一分钟内做了多少次。然后生成 1000 个整数(价值 4K 的内存)并将它们保存到文件中 1 分钟,您会惊讶于您的磁盘 I/O 有多好
【解决方案2】:

即使您的代码是多线程的;因为你所有的线程都试图访问同一个文件..它不会有太大的不同..因为在这种情况下,即使有很多线程正在运行;在某一时刻,除了 1 之外的所有内容都将等待获取对文件的写访问权限。

【讨论】:

  • 他们不访问同一个文件。每个人都写入新文件。"_frameCount++" 负责它。
  • @MichaelIV 他们仍然使用同一个磁盘。磁盘 I/O 是你的敌人。您尝试写入的文件越多,从一个文件到另一个文件写入磁盘的停机时间就越长。
【解决方案3】:

为什么你认为它会更快?磁盘不是多线程的。

【讨论】:

  • 这根本不存在,因为在物理驱动器方面甚至不存在线程。
  • @MattWestlake 正是我的观点。 CPU 中的多个线程没有延伸到磁盘,那么为什么它们会更快地执行 I/O。多个线程在磁盘上按顺序排列,如果不是之前的话。他们没有任何意义。
猜你喜欢
  • 1970-01-01
  • 2013-07-27
  • 2015-11-26
  • 1970-01-01
  • 2016-02-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多