很难以相信构造p[u+1]发生在代码的最内层循环中的几个地方,我保持这样,在正确运行数天的操作中,对其进行微观优化会产生数小时的差异.
通常*((p+u)+1)是最有效的.有时候*(p+(u+1))效率最高.很少*((p+1)+u)是最好的.(但通常优化器可以转换*((p+1)+u)为*((p+u)+1)后者更好,并且不能*(p+(u+1))与其他任何一个转换).
p是一个指针,u是一个无符号的.在实际代码中,它们中的至少一个(更可能两者)在表达式被评估的点处已经在寄存器中.这些事实对我的问题至关重要.
在32位(在我的项目放弃支持之前)中,所有三个都具有完全相同的语义,并且任何一半不错的编译器只选择三者中最好的并且程序员永远不需要关心.
在这些64位用法中,程序员知道这三者具有相同的语义,但编译器不知道.就编译器所知,何时u从32位扩展到64位的决定会影响结果.
什么是最简洁的方法告诉编译器这三个语义是相同的,编译器应该选择最快的?
在一个Linux 64位编译器中,我几乎在那里p[u+1L]使编译器在通常最好*((p+u)+1)和有时更好之间智能地选择*(p+( (long)(u) + 1) ).在极少数情况下*(p+(u+1))仍然比第二种更好,有点丢失.
显然,这在64位Windows中没有用.既然我们已经放弃了32位支持,那么可能p[u+1LL]足够便携且足够好.但我能做得更好吗?
请注意,使用std::size_t而不是unsignedfor u将消除整个问题,但会在附近产生更大的性能问题.铸造u到std::size_t那里几乎是足够好,也许我能做到的最好.但对于一个不完美的解决方案来说,这是非常冗长的.
简单编码(p+1)[u]使选择更可能是最佳选择p[u+1].如果代码的模板化程度较低且更稳定,我可以将它们全部设置为(p+1)[u]然后进行配置文件,然后再将其切换回p[u+1].但是模板化往往会破坏这种方法(在配置文件的许多地方出现单一的源代码行,导致严重的时间,但不是单独的严重时间).
对此应该有效的编译器是GCC,ICC和MSVC.
假设有必要计算打包浮点数据的倒数或倒数平方根.两者都可以轻松完成:
__m128 recip_float4_ieee(__m128 x) { return _mm_div_ps(_mm_set1_ps(1.0f), x); }
__m128 rsqrt_float4_ieee(__m128 x) { return _mm_div_ps(_mm_set1_ps(1.0f), _mm_sqrt_ps(x)); }
Run Code Online (Sandbox Code Playgroud)
这种方法效果很好但很慢:根据指南,它们在Sandy Bridge上进行了14次和28次循环(吞吐量).对应的AVX版本在Haswell上几乎占用相同的时间.
另一方面,可以使用以下版本:
__m128 recip_float4_half(__m128 x) { return _mm_rcp_ps(x); }
__m128 rsqrt_float4_half(__m128 x) { return _mm_rsqrt_ps(x); }
Run Code Online (Sandbox Code Playgroud)
它们只需要一到两个时间周期(吞吐量),从而大大提升了性能.但是,它们非常接近:它们产生的结果相对误差小于1.5*2 ^ -12.鉴于单精度浮点数的机器epsilon是2 ^?24,我们可以说这种近似具有大约一半的精度.
似乎可以添加Newton-Raphson迭代以产生具有单精度的结果(可能不像IEEE标准所要求的那样精确),参见GCC,ICC,LLVM上的讨论.理论上,相同的方法可用于双精度值,产生半精度或单精度或双精度.
我有兴趣为float和double数据类型以及所有(half,single,double)精度实现此方法的实现.处理特殊情况(除以零,sqrt(-1),inf/nan等)不是必需的.此外,我不清楚这些例程中的哪一个比普通的IEEE编译解决方案更快,哪个更慢.
以下是对答案的一些小限制,请:
欢迎任何性能评估,测量和讨论.
以下是具有一次NR迭代的单精度浮点数的版本:
__m128 recip_float4_single(__m128 x) {
__m128 res = _mm_rcp_ps(x);
__m128 muls …Run Code Online (Sandbox Code Playgroud) Problem Description:
References: Fun With Strings
Based on the problem description, a naive approach to find sum of length of LCP for all possible substrings (for a given string) is as follows :
#include <cstring>
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
using std::string;
int lcp(string str1, string str2)
{
string result;
int n1 = str1.length(), n2 = str2.length();
// Compare str1 and str2
for (int i=0, j=0; i<=n1-1 && j<=n2-1; i++,j++)
{
if (str1[i] != str2[j])
break;
result.push_back(str1[i]); …Run Code Online (Sandbox Code Playgroud) 我在MSVC2013中进行混合调试存在严重问题.从本机C++ DLL调用COM方法后,调试器不再停止在断点处.
上图显示了代码的整体结构.
我有一个包含大约10个C#项目的解决方案,大约50个C++本机项目,以及一个C++/CLI项目,作为托管和本地世界之间的桥梁.启动项目是一个C#WPF项目(GUI Application),它Bridge在内部调用C++/cli project(),后者又调用各种本机C++ Dll(Various libraries).或者,我可以将C++控制台应用程序(Service console app)作为启动项目,仅用于测试目的.
我已经实现了一个库来从Autodesk Inventor文档文件中导入一些信息.Inventor Apprentice COM服务器(Inventor Apprentice图片上)用于实现它,可以与Inventor View 2015一起免费下载.作为第一步,导入是在独立的本机C++控制台应用程序中实现的,一切正常.然后它被改编为在整个基础架构中用作本机C++ dll(Import library),并且调试地狱开始了.
"调试坏了".在调试版本中,在调用以下COM方法之后Import library:
auto pComponentDefinitions = pDocument->GetComponentDefinitions();
Run Code Online (Sandbox Code Playgroud)
C++代码中的断点不再受到影响.即使我在另一个DLL的代码中设置断点,它也不会被命中.断点仍然可视化为完整的红色圆圈,因此这与PDB问题无关.应用程序本身继续执行,一段时间后我可以在GUI中看到正确的数据导入结果,这意味着Import library已正确执行.之后,我可以暂停GUI Application使用Break All按钮,在这种情况下,主线程显示在Inventor的一个dll(rse.dll)中,这可能不是真的,因为该线程已完成导入并且甚至返回了正确的结果.
在"输出"窗口中,我可以看到以下消息,在有问题的COM方法调用期间出现(访问违规在Apprentice中似乎正常):
First-chance exception at 0x000007FEDD451F0C (rse.dll) in GUIApplication.exe: 0xC0000005: Access violation writing location 0x000007FFFDE3AFCC.
The Common Language Runtime cannot stop at this exception. Common causes include: …Run Code Online (Sandbox Code Playgroud) 众所周知,C++ 11的标准库允许轻松地将字符串从UTF-8编码转换为UTF-16.但是,以下代码成功转换无效的UTF-8输入(至少在MSVC2010下):
#include <codecvt>
#include <locale>
#include <string>
int main() {
std::string input = "\xEA\x8E\x97" "\xE0\xA8\x81" "\xED\xAE\x8D";
std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> converter;
try {
std::u16string output = converter.from_bytes(input.data());
printf("Converted successfully\n");
}
catch(std::exception &e) {
printf("Error: %s\n", e.what());
}
}
Run Code Online (Sandbox Code Playgroud)
这里的字符串包含9个字节,3个代码点.最后一个代码点是0xDB8D,它是无效的(适合代理范围).
是否可以仅使用现代C++的标准库来检查UTF-8字符串的完美有效性?这里我的意思是不允许维基百科文章中描述的所有无效案例.
如何只获取float的整数部分?所以,我有一个浮点数组:x [4] = {5.0,13.0,25.0,41.0}; 我把它放在xmm0然后我正在制作它的sqrt.我还需要一个命令来帮助只占用这个sqrt的int部分.例如,5的sqrt将是2.236068,我在答案
代码中只需要2.0 :
__asm
{
movups xmm0, x
sqrtps xmm0, xmm0
//here need some command
movups x, xmm0
}
Run Code Online (Sandbox Code Playgroud) 我有一个MSVC2013解决方案与C#(托管)和C++(本机)项目.一个C#项目被设置为启动项目.我想通过调试启动这个项目,这通常只需按下F5即可在devenv中实现.
但是,我想在纯本机模式下启动调试器(即没有托管调试).我无法通过更改C#项目的设置来实现此行为:它只有一个选项"启用本机代码调试",它允许启用或禁用本机调试.我知道的唯一标准方法是在没有调试的情况下启动应用程序,然后仅选择本机调试附加到进程.
有没有办法自动化这个过程?理想情况下,按一个按钮应足以启动仅本机调试.也许某些扩展可以简化这项任务.
PS我在混合模式调试中遇到了一个令人讨厌的错误,在我的情况下完全破坏了调试.这个错误本身不是问题的主题,它只是解释了为什么使用C#启动项目进行本机调试可能有用(并且对我个人有用).
我有两个稀疏的向量X和Y,并希望得到O(m + n)中的点积,其中m和n是X和Y中非零元素的数量.我能想到的唯一方法是选择每个元素在向量X中并遍历向量Y以查找是否存在具有相同索引的元素.但这需要O(m*n).我将矢量实现为链表,每个节点都有一个元素.
我正在使用长int数据,我试图确定数组中的最小元素.我知道循环遍历数组的传统方法来找到最小值.这个问题是检查是否有其他方法可以加快速度.
这个数组的某些属性可能可以帮助我们加快速度,但我不确定如何.
该数组恰好有8个长整数.每当我们调用该函数时,我们从数组中找到一个min,并且数字被另一个数字替换,我们重复这一步.(至少80亿次)
我想要记住下一次迭代的第二大数字(因为我们将在当前迭代中对它们进行比较).与通过数组的线性实现相比,这是否有用?
也允许排序,但我们必须以某种方式记住使用临时数组的原始位置.这会更有效吗?
还能以某种方式使用SIMD来确定长期最小值吗?即使是毫秒级的加速也很有用,因为我正在进行数十亿次此操作.
c++ ×7
algorithm ×3
performance ×3
c ×2
c# ×2
debugging ×2
sse ×2
arrays ×1
assembly ×1
avx ×1
big-o ×1
breakpoints ×1
optimization ×1
simd ×1
string ×1
suffix-tree ×1
utf-8 ×1