在研究Python和C++之间的性能折衷的同时,我设计了一个小例子,主要关注一个愚蠢的子串匹配.
这是相关的C++:
using std::string;
std::vector<string> matches;
std::copy_if(patterns.cbegin(), patterns.cend(), back_inserter(matches),
[&fileContents] (const string &pattern) { return fileContents.find(pattern) != string::npos; } );
Run Code Online (Sandbox Code Playgroud)
以上是用-O3构建的.
这是Python:
def getMatchingPatterns(patterns, text):
return filter(text.__contains__, patterns)
Run Code Online (Sandbox Code Playgroud)
它们都采用大量模式和输入文件,并使用哑子搜索将模式列表过滤到文件中找到的模式列表.
版本是:
令我惊讶的是表现.我在低规格的Ubuntu上运行,Python的速度提高了大约20%.在具有cygwin的中型PC上也是如此 - Python速度提高了两倍.Profiler显示99 +%的周期用于字符串匹配(字符串复制和列表推导是无关紧要的).
显然,Python实现是本机C,我希望它与C++大致相同,但并不期望它快.
与gcc相比,对相关CPython优化的任何见解都是最受欢迎的.
作为参考,这里是完整的例子.输入只需要一组50K HTLM(每次测试都从磁盘读取,没有特殊的缓存):
蟒蛇:
import sys
def getMatchingPatterns(patterns, text):
return filter(text.__contains__, patterns)
def serialScan(filenames, patterns):
return zip(filenames, [getMatchingPatterns(patterns, open(filename).read()) for filename in filenames])
if __name__ == "__main__":
with open(sys.argv[1]) as filenamesListFile:
filenames = filenamesListFile.read().split()
with open(sys.argv[2]) as patternsFile:
patterns …Run Code Online (Sandbox Code Playgroud) 这更像是一个哲学问题,而不是实际的代码片段,但也许C++专家可以启发我(并且如果已经被问过就道歉).
我一直在阅读Meyers的"Effective Modern C++"一书中的第15项,以及这个主题:隐含的constexpr?(加上合理数量的谷歌搜索).该项目constexpr用于表达式的使用,即它定义了在给定编译时输入的情况下可以返回编译时间值的函数.此外,我提到的StackOverflow线程表明,一些编译器完全能够自己计算出哪些函数调用结果在编译时是已知的.
因此,问题是:constexpr与定义何时编译器应该派生并允许静态/编译时值相比,为什么添加到标准中?
我意识到这使得各种仅限编译(例如std::array<T, constexpr>)的定义不太可预测,但另一方面,根据Meyers的书,constexpr是界面的一部分,...,如果你删除它,你可能会造成任意大量的客户端代码停止编译.因此,不仅有明确的constexpr要求人们记住添加它,它还会为接口添加永久语义.
澄清:这个问题不是为什么constexpr要使用.我很欣赏能够以编程方式获得编译时值非常有用,并且在很多场合自己使用它.这是一个问题,为什么在编译器可能自己推断出const-time行为的情况下它是强制性的.
澄清号码 2:这是一个代码片段,显示编译器不会自动推断出,我在这种情况下使用了g ++.
#include <array>
size_t test()
{
return 42;
}
int main()
{
auto i = test();
std::array<int, i> arrayTst;
arrayTst[1] = 20;
return arrayTst[1];
}
Run Code Online (Sandbox Code Playgroud)
std::array声明无法编译,因为我没有定义test()为constexpr,这当然是按照标准.如果标准不同,那么没有任何东西可以阻止gcc独立计算test()总是返回一个常量表达式.
这个问题不是问"标准定义了什么",而是"为什么标准就是这样"?
我试图找出带有正则表达式匹配的Python,Cython和纯C之间的违反直觉的性能差异。
有一个小的示例程序,该程序使用源文本文件(17 KB),2000个单词的字典,并使用这些单词(word1 | word2 | ...)创建一个正则表达式,并在源文件中找到该词典的所有实例。 。
首先,我完成了一个纯Python实现,如下所示:
def scanFile(filename, patterns):
pattern_regex = re.compile('|'.join(patterns))
pageContent = open(filename).read()
matchingPatterns = set()
for matchObj in pattern_regex.finditer(pageContent):
matchingPatterns.add(matchObj.group(0))
return matchingPatterns
Run Code Online (Sandbox Code Playgroud)
然后,我尝试通过使用Cython(regex.h而不是Python的re模块)重新实现相同的功能来优化此功能。
cdef extern from "regex.h" nogil:
ctypedef struct regmatch_t:
int rm_so
int rm_eo
ctypedef struct regex_t:
pass
int REG_EXTENDED
int regcomp(regex_t* preg, const char* regex, int cflags)
int regexec(const regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags)
void regfree(regex_t* preg)
def matchPatterns(bytes pageContent, bytes regex): …Run Code Online (Sandbox Code Playgroud)