微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在 C++ 中读取镶木地板文件比在 python 中慢

如何解决在 C++ 中读取镶木地板文件比在 python 中慢

我已经编写了使用 c++ 和 python 读取相同镶木地板文件代码。 python读取文件的时间比c++少得多,但众所周知,c++的执行速度比python快。我在这里附上了代码 -

#include <arrow/api.h>
#include <parquet/arrow/reader.h>
#include <arrow/filesystem/localfs.h>
#include <chrono>
#include <iostream>

int main(){
   // ...
   arrow::Status st;
   arrow::MemoryPool* pool = arrow::default_memory_pool();
   arrow::fs::LocalFileSystem file_system;
   std::shared_ptr<arrow::io::RandomAccessFile> input = file_system.OpenInputFile("data.parquet").ValueOrDie();

   // Open Parquet file reader
   std::unique_ptr<parquet::arrow::FileReader> arrow_reader;
   st = parquet::arrow::OpenFile(input,pool,&arrow_reader);
   if (!st.ok()) {
      // Handle error instantiating file reader...
   }

   // Read entire file as a single Arrow table
   std::shared_ptr<arrow::Table> table;
   auto t1 = std::chrono::high_resolution_clock::Now();
   st = arrow_reader->ReadTable(&table);
   auto t2 = std::chrono::high_resolution_clock::Now();
   if (!st.ok()) {
      // Handle error reading Parquet data...
   }
   else{
       auto ms_int = std::chrono::duration_cast<std::chrono::milliseconds> (t2 - t1);
       std::cout << "Time taken to read parquet file is : " << ms_int.count() << "ms\n";
   }
}

我在python中使用的代码是-

#!/usr/bin/env python3
import pandas as pd
import pyarrow as pa
import pyarrow.parquet as pq
import time

start_time = time.time()

table = pq.read_table('data.parquet')

end_time = time.time()

print("Time taken to read parquet is : ",(end_time - start_time)*1000,"ms")

在为大约 87mb 的文件运行 c++ 代码时,c++ 的输出是 -

读取 parquet 文件所需的时间为:186 毫秒

虽然对于 python 输出是 -

读取 parquet 所需的时间为:108.66141319274902 毫秒

为什么c++和python中read_table函数的执行时间相差这么大?

解决方法

python pq.read_table 基于与您在示例中使用的完全相同的 C++ API(在后台它也使用 C++ parquet::arrow::FileReader),因为 Python 和 C++ API 都来自同一个 Arrow 项目。
因此,除了一点点 Python 调用堆栈开销外,预计两种方式都将执行相同的操作。

然而,您可以指定/调整多个选项以提高性能,这可以解释您的情况的差异。例如,python 函数默认会并行读取文件(您可以指定 use_threads=False 以禁用此功能)。另一方面,C++ FileReader 默认不这样做(检查 set_use_threads)。默认情况下,python 阅读器可能还会设置其他选项。
此外,编译 C++ 示例时的确切构建标志也会产生影响。

,

Python 模块很可能绑定到使用诸如 c++ 或使用 cython 之类的语言编译的函数。因此,python 模块的实现可能具有更好的性能,这取决于它如何读取文件或处理数据。

,

1 秒是 1000 毫秒。所以差别不是那么大。除此之外,python 的许多功能经常使用 CPython,这使它们处于一个非常公平的竞争环境中。然后它只取决于函数的编写和优化程度。在这种情况下,python 函数可能比 C++ 函数更优化。

,

如果您想进行比较,请尝试使用此 CPP 代码:

#include <cassert>
#include <chrono>
#include <cstdlib>
#include <iostream>

using namespace std::chrono;

#include <arrow/api.h>
#include <arrow/filesystem/api.h>
#include <parquet/arrow/reader.h>

using arrow::Result;
using arrow::Status;

namespace {

Result<std::unique_ptr<parquet::arrow::FileReader>> OpenReader() {
  arrow::fs::LocalFileSystem file_system;
  ARROW_ASSIGN_OR_RAISE(auto input,file_system.OpenInputFile("data.parquet"));

  parquet::ArrowReaderProperties arrow_reader_properties =
      parquet::default_arrow_reader_properties();

  arrow_reader_properties.set_pre_buffer(true);
  arrow_reader_properties.set_use_threads(true);

  parquet::ReaderProperties reader_properties =
      parquet::default_reader_properties();

  // Open Parquet file reader
  std::unique_ptr<parquet::arrow::FileReader> arrow_reader;
  auto reader_builder = parquet::arrow::FileReaderBuilder();
  reader_builder.properties(arrow_reader_properties);
  ARROW_RETURN_NOT_OK(reader_builder.Open(std::move(input),reader_properties));
  ARROW_RETURN_NOT_OK(reader_builder.Build(&arrow_reader));

  return arrow_reader;
}

Status RunMain(int argc,char **argv) {
  // Read entire file as a single Arrow table
  std::shared_ptr<arrow::Table> table;
  for (auto i = 0; i < 10; i++) {
    ARROW_ASSIGN_OR_RAISE(auto arrow_reader,OpenReader());
    auto t1 = std::chrono::high_resolution_clock::now();
    ARROW_RETURN_NOT_OK(arrow_reader->ReadTable(&table));
    std::cout << table->num_rows() << "," << table->num_columns() << std::endl;
    auto t2 = std::chrono::high_resolution_clock::now();
    auto ms_int =
        std::chrono::duration_cast<std::chrono::milliseconds>(t2 - t1);
    std::cout << "Time taken to read parquet file is : " << ms_int.count()
              << "ms\n";
  }

  return Status::OK();
}

} // namespace

int main(int argc,char **argv) {
  Status st = RunMain(argc,argv);
  if (!st.ok()) {
    std::cerr << st << std::endl;
    return 1;
  }
  return 0;
}

然后与此python代码进行比较:

#!/usr/bin/env python3                                                                                                                                                                                     
import pandas as pd
import pyarrow as pa
import pyarrow.parquet as pq
import time

for i in range(10):
    parquet_file = pq.ParquetFile('/home/pace/experiments/so4/data.parquet',pre_buffer=True)
    start_time = time.time()
    table = parquet_file.read()
    end_time = time.time()
    print("Time taken to read parquet is : ",(end_time - start_time)*1000,"ms")

在我的系统上运行 10 次后,t 检验无法区分这两种分布 (p=0.64)。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?