python - 为什么这段 C 代码通过 Python 的 ctypes 运行时的执行速度是直接运行时的一半?

标签 python c

我正在玩弄 Python 和 C 的接口(interface),作为一个简单的测试,我比较了 C 中的 SuperFastHash 实现与 Python 中的 SuperFastHash 实现的速度,然后查看仅从 Python 调用 C 版本的结果.这导致了一个令人惊讶的结果。这是 C 代码:http://pastebin.com/Hc7iqzH1我的基准测试 main() 在底部。

当使用 gcc -O3 -lrt hash_test.c 编译并运行可执行文件时,我得到以下结果:secs: 20, hashes: 650449494, hashes/sec: 32522474.700000, Khashes/秒:32522.474700

当使用 gcc -lrt -O3 -fPIC -shared hash_test.c -o super.so 编译 .so 文件,并运行包含 Python (2.7) 的脚本时

from ctypes import *
lib = cdll.LoadLibrary('./super.so')
lib.main()

我得到的结果是:secs: 20, hashes: 306842579, hashes/sec: 15342128.950000, Khashes/sec: 15342.128950

在相同的时间内,这只计算了直接程序调用的大约一半的哈希值。为什么?

最佳答案

性能下降的原因是编译器在共享库的情况下无法优化。它没有内联对 SuperFastHash 的调用。但这与 jxh 所建议的 PIC 格式无关。

如果您使用函数代码手动内联对 SuperFastHash 的调用,您会发现 Python 代码将产生与原始 C 代码相同的性能。这是我的版本:https://gist.github.com/cod3monk/9821796

另一方面,可以使用以下 C 代码重现 python 的不良性能:<​​/p>

#include <time.h>
#include <stdio.h>
#include <unistd.h>

uint32_t SuperFastHash (const char * data, int len);

int main(void) {
      struct timespec start, end;
  long secs;
  long hashes = 0;
  char data[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20};
  clock_gettime(CLOCK_MONOTONIC, &start);
  clock_gettime(CLOCK_MONOTONIC, &end);
  while ((secs = end.tv_sec - start.tv_sec) < 20) {
    uint32_t hash = SuperFastHash(data, 20);
    data[hash % 20] += 1;
    clock_gettime(CLOCK_MONOTONIC, &end);
    ++hashes;
  }

  printf("secs: %ld, hashes: %ld, hashes/sec: %f, Khashes/sec: %f\n", secs, hashes, hashes/20.0,
      hashes/20.0/1000.0);
  return 0;
}

现在使用 gcc -O3 the_above_code.c super.so -lrt 编译并运行它 (LD_LIBRARY_PATH=. ./a.out)。

关于python - 为什么这段 C 代码通过 Python 的 ctypes 运行时的执行速度是直接运行时的一半?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22700082/

相关文章:

c - 为什么在位溢出的情况下丢弃 MSB?

c++ - 如何使用 scanf 从用户输入中获取字符串 ( char * ),由双引号分隔并包含空格

python - 处理高度不平衡数据的正确方法——二元分类

python - django-post_office - 使用基于文件而不是基于数据库的电子邮件模板

python - 有效地检查字符串是否由 Python 中的一个字符组成

c - 在 C 中采用 ENUM 参数的函数中的错误

c - C90 中真的不允许使用可变长度数组吗?

c++ - 如何将 WebAssembly 编译成常规汇编/ native 代码(或 Cpp 等)?

python - 对 openCV 中的某些特定点应用过滤器

python - 如何根据文本文件创建字典?