簡體   English   中英

共享庫與打開進程性能

[英]Shared library vs. opening a process performance

我有一定的 Python 代碼基礎(Flask 服務器)。 我需要服務器執行性能關鍵操作,我決定在 C++ 中實現該操作。 但是,由於C++部分還有其他依賴,嘗試了ctypesboost.python沒有結果(沒有找到符號,其他庫甚至在設置環境時等等,基本上都有問題)。 我相信一個合適的替代方案是我只需將 C++ 部分編譯為可執行文件(需要單個函數/過程)並使用commandssubprocess進程從 python 運行它,例如通過stdin/out進行通信。 我唯一擔心的是這會減慢程序的速度,因為我無法創建共享的 object 庫,從 python 調用它的 function 庫,我無法直接進行基准測試。

當我將 C++ 代碼編譯成可執行文件並使用一些示例數據運行它時,程序需要~5s才能運行。 這不考慮從 python 打開進程,也不考慮在進程之間傳遞數據。

問題是:與創建一個新進程來運行該過程相比,通過使用帶有 SO 的 ctypes/boost 可以期望多大的加速? 如果我認為這個數字足夠大,它會激勵我解決遇到的問題,基本上,我是在問是否值得

如果您在使用 Boost.Python 創建綁定時遇到困難,您可以通過 c 函數手動公開您的 API 並通過 FFI 使用它們。

這是一個簡單的例子,它簡要解釋了我的想法。 首先,您創建了一個共享庫,但在此處添加了一些額外的函數,在示例中我將其放入extern "C"部分。 必須使用extern "C"否則 function 名稱將被破壞,並且它們的實際名稱可能與您聲明的名稱不同:

#include <cstdint>
#include <cstdio>

#ifdef __GNUC__
#define EXPORT __attribute__ ((visibility("default")))
#else // __GNUC__
#error "Unsupported compiler"
#endif // __GNUC__

class data_processor {
public:
  data_processor() = default;

  void process_data(const std::uint8_t *data, std::size_t size) {
    std::printf("processing %zu bytes of data at %p\n", size, data);
  }
};

extern "C" {
EXPORT void *create_processor() {
  return new data_processor();
}

EXPORT void free_processor(void *data) {
  delete static_cast<data_processor *>(data);
}

EXPORT void process_data(void *object, const std::uint8_t *data, const std::uint32_t size) {
  static_cast<data_processor *>(object)->process_data(data, size);
}
}

然后在 python 中創建 function 綁定。 如您所見,function 聲明與下面的 cpp 文件中的聲明幾乎相同。 我只使用了內置類型(如void *uint8_t和任何東西,但我相信 FFI 也允許您聲明和使用自定義結構):

from cffi import FFI

mylib_api = FFI()
mylib_api.cdef("""
    void *create_processor();
    void free_processor(void *object);
    void process_data(void *object, const uint8_t *data, uint32_t size);
""")
mylib = mylib_api.dlopen("mylib.so-file-location")

processor = mylib.create_processor()
try:
    buffer = b"buffer"
    mylib.process_data(processor, mylib_api.from_buffer("uint8_t[]", python_buffer=buffer), len(buffer))
finally:
    mylib.free_processor(processor)

基本上就是這樣。

在我看來,當沒有其他方法起作用時,交互處理將是最后的手段,因為:

  • 你需要付出很多努力來實現你的通信協議的細節,如果你使用流行的東西,可能會出現很多問題,尤其是從 c++ 端;
  • 就處理器時間而言,進程間通信通常更昂貴。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM