文本迭代、汇编与C++

文本迭代、汇编与C++,c++,string,assembly,web,iteration,C++,String,Assembly,Web,Iteration,我正在制作一个程序,其中is经常读取从web接收的文本块,寻找特定字符并相应地解析数据。我变得相当熟练C++,并且使它工作得很好,然而,程序会比快吗? for(size_t len = 0;len != tstring.length();len++) { if(tstring[len] == ',') stuff(); } 使用cmp和jz/jnz的内联汇编例程会更快吗?我不想浪费时间与asm一起工作,因为我可以说我使用了它,但为了真正的速度目的 谢谢, 使用cmp和j

我正在制作一个程序,其中is经常读取从web接收的文本块,寻找特定字符并相应地解析数据。我变得相当熟练C++,并且使它工作得很好,然而,程序会比

快吗?
for(size_t len = 0;len != tstring.length();len++) {
    if(tstring[len] == ',')
        stuff();
}
使用cmp和jz/jnz的内联汇编例程会更快吗?我不想浪费时间与asm一起工作,因为我可以说我使用了它,但为了真正的速度目的

谢谢,

使用cmp和jz/jnz的内联汇编例程会更快吗

也许,也许不是。这取决于stuff的功能、tstring的类型和范围以及程序集的外观

首先,测量可维护C++代码的速度。只有当这个循环控制程序的速度时,你才应该考虑重写它。 如果您选择重写它,请使这两个实现都可用,并对它们进行比较测量。只有在速度更快且速度提高很重要的情况下,才使用可维护性较差的版本。此外,由于您已经准备好了原始版本,未来的读者将能够理解您的意图,即使他们不太了解asm

使用cmp和jz/jnz的内联汇编例程会更快吗

也许,也许不是。这取决于stuff的功能、tstring的类型和范围以及程序集的外观

首先,测量可维护C++代码的速度。只有当这个循环控制程序的速度时,你才应该考虑重写它。


如果您选择重写它,请使这两个实现都可用,并对它们进行比较测量。只有在速度更快且速度提高很重要的情况下,才使用可维护性较差的版本。此外,由于您已经准备好了原始版本,未来的读者将能够理解您的意图,即使他们不太了解asm。

不可能。您的循环非常简单,优化器失去对代码进行推理的能力的成本将远远高于您可能获得的任何性能。这不是SSE内部函数或引导加载程序,而是一个简单的循环。

不可能。您的循环非常简单,优化器失去对代码进行推理的能力的成本将远远高于您可能获得的任何性能。这不是SSE内部函数或引导加载程序,而是一个简单的循环。

逐个检查字符并不是最快的方法。也许你应该试试这样的东西,看看它是否更快

string s("xxx,xxxxx,x,xxxx");
string::size_type pos = s.find(',');  
while(pos != string::npos){
    do_stuff(pos);
    pos = s.find(',', pos+1);       
}

循环的每次迭代都会给你一个“,”字符的下一个位置,因此程序只需要几个循环就可以完成任务。

逐个检查字符并不是最快的事情。也许你应该试试这样的东西,看看它是否更快

string s("xxx,xxxxx,x,xxxx");
string::size_type pos = s.find(',');  
while(pos != string::npos){
    do_stuff(pos);
    pos = s.find(',', pos+1);       
}

循环的每次迭代都会给你一个“,”字符的下一个位置,因此程序只需要几个循环就可以完成任务。

使用普通的旧jz/jnz的内联汇编例程不太可能比你现有的更快;也就是说,您的代码中存在一些低效之处:

每次循环迭代检索一次tstring.length;那是不必要的。 您使用的是随机索引,tstring[len],这可能比使用前向迭代器更昂贵。 你在循环中调用东西;根据具体操作,让循环先在字符串中构建一个位置列表可能会更快,这样扫描的字符串和扫描代码就可以保持缓存热状态,而不会被任何东西逐出,然后才迭代这些结果。 已经有了一个可能的低级别优化标准库函数,可用于这种扫描。C++ STL也可能为了优化目的而被优化,或者可能在字符专门化中使用Schchr。 特别是,strchr使用pcmpeqb、maskmov。。。以及使用字符串op pcmpistri实现的bsf或SSE4.2;有关执行此操作的示例/实际SSE代码,请检查例如Linux上使用的代码。另请参阅适当命名的网站的参考资料和评论

我的建议:检查您的库实现/文档,和/或为您的程序实际生成的汇编代码。您可能已经在使用fast代码了。。。或者,如果您从手动逐个字符的简单搜索切换到仅使用std::string::find或strchr,则会出现这种情况。
如果这是超高速关键,那么已知/测试的实现所使用的strchr内联汇编代码将消除函数调用并获得几个周期。取决于你的要求。。。代码、基准测试、变化、再次基准测试,

使用普通的旧jz/jnz的内联汇编例程不太可能比您现有的更快;也就是说,您的代码中存在一些低效之处:

每次循环迭代检索一次tstring.length;那是不必要的。 您正在使用随机索引,tstring[len],这可能是一个更简单的方法 -比使用前向迭代器更昂贵的操作。 你在循环中调用东西;根据具体操作,让循环先在字符串中构建一个位置列表可能会更快,这样扫描的字符串和扫描代码就可以保持缓存热状态,而不会被任何东西逐出,然后才迭代这些结果。 已经有了一个可能的低级别优化标准库函数,可用于这种扫描。C++ STL也可能为了优化目的而被优化,或者可能在字符专门化中使用Schchr。 特别是,strchr使用pcmpeqb、maskmov。。。以及使用字符串op pcmpistri实现的bsf或SSE4.2;有关执行此操作的示例/实际SSE代码,请检查例如Linux上使用的代码。另请参阅适当命名的网站的参考资料和评论

我的建议:检查您的库实现/文档,和/或为您的程序实际生成的汇编代码。您可能已经在使用fast代码了。。。或者,如果您从手动逐个字符的简单搜索切换到仅使用std::string::find或strchr,则会出现这种情况。
如果这是超高速关键,那么已知/测试的实现所使用的strchr内联汇编代码将消除函数调用并获得几个周期。取决于你的要求。。。代码、基准测试、变化、再次基准测试,…

比您的循环更合适。在确定此部分是一个热点并用尽所有可能的替代方案之前,甚至不要考虑汇编程序。通常,过早优化是所有邪恶的根源Donald Knuth。一般来说,除非你有确凿的证据证明你需要从分析和基准测试中得到帮助,否则不要进行优化。但是在这种情况下。。。事实上,你可以用C例程或是,甚至是一些在线汇编程序来做得更好,而不是标准的C++字符串类型。嗯…@w00te-你是认真的吗?拆分输入缓冲区并使用多个线程对其进行操作?真正地我真希望你只是在开玩笑。如果您的系统除了这个文本搜索操作之外做的很少,并且您有多个内核,并且您知道您有多少个内核,并且您只创建与您有多少个内核一样多的线程,那么这将加快速度。如果您创建的线程在同一个内核上运行,此解决方案将降低搜索操作的速度,而不是提高搜索速度。@phonetagger 1如果您正在处理大量数据,这是常见的。2即使是我3-4岁的笔记本电脑也是多核的。如果这在工业中使用,这将是非常普遍的,如果是大学,这是一个很好的实践。3为什么要在同一个内核上运行多线程进行数据处理?那太愚蠢了。比你的循环更合适一点。在你确定这一部分是一个热点,并且用尽了所有可能的选择之前,甚至不要考虑汇编程序。一般来说,过早优化是万恶之源Donald Knuth。一般来说,除非你有确凿的证据证明你需要从分析和基准测试中得到帮助,否则不要进行优化。但是在这种情况下。。。事实上,你可以用C例程或是,甚至是一些在线汇编程序来做得更好,而不是标准的C++字符串类型。嗯…@w00te-你是认真的吗?拆分输入缓冲区并使用多个线程对其进行操作?真正地我真希望你只是在开玩笑。如果您的系统除了这个文本搜索操作之外做的很少,并且您有多个内核,并且您知道您有多少个内核,并且您只创建与您有多少个内核一样多的线程,那么这将加快速度。如果您创建的线程在同一个内核上运行,此解决方案将降低搜索操作的速度,而不是提高搜索速度。@phonetagger 1如果您正在处理大量数据,这是常见的。2即使是我3-4岁的笔记本电脑也是多核的。如果这在工业中使用,这将是非常普遍的,如果是大学,这是一个很好的实践。3为什么要在同一个内核上运行多线程进行数据处理?这太蠢了。SSE可以让扫描一个字符串以查找像这样的单个字符的速度大大加快。但问题是关于cmp的,所以你没有错,的确。不过,这完全取决于材料。但是,我承认自动矢量化不是编译器的强项,使用内部函数或手写汇编也不是特别不合理。SSE可以使扫描字符串以查找单个字符的速度大大加快。但问题是关于cmp的,所以你没有错,的确。不过,这完全取决于材料。然而,我承认自动矢量化不是编译器的强项,使用内部函数或手写汇编也不是特别不合理,这只是逐个检查字符。没有其他方法可以在任意字符串中搜索单个字符。是的,就像我说的,我不知道如何找到我
thod在内部工作,但我相信它针对任务进行了很好的优化。他总是可以检查速度,然后发现,我只是想给出一个替代的解决方案。我将使用这个循环,而不是ASM。在本项目的稍后部分,我将阅读可能存在的数百个小文件,其中每行数据都很重要,在ASM中我很容易犯错误。@CollinBiedenkapp您也可以将do_stuff定义为一个内联函数,因为常规函数调用会做很多工作,比如保存寄存器,将参数和分支程序复制到新位置。内联函数是以行方式展开的,这样可以避免函数调用开销。但是请注意,内联规范只是对编译器的一个请求,他可能会选择忽略它,这只是一个接一个地检查字符。没有其他方法可以在任意字符串中搜索单个字符。是的,就像我说的,我不知道find方法在内部是如何工作的,但我相信它已经针对该任务进行了很好的优化。他总是可以检查速度,然后发现,我只是想给出一个替代的解决方案。我将使用这个循环,而不是ASM。在本项目的稍后部分,我将阅读可能存在的数百个小文件,其中每行数据都很重要,在ASM中我很容易犯错误。@CollinBiedenkapp您也可以将do_stuff定义为一个内联函数,因为常规函数调用会做很多工作,比如保存寄存器,将参数和分支程序复制到新位置。内联函数是以行方式展开的,这样可以避免函数调用开销。但是请注意,内联规范只是对编译器的一个请求,他可能会选择忽略它。