c#语言float转换int,关于C#:在x86上将float转换为int的最快方法是什么
在x86 CPU上将浮点数转换为int的最快方法是什么。 优选在C或组件中(可以在C中内嵌)以获得以下任何组合:
32/64/80位浮点数 - > 32/64位整数
我正在寻找一些比让编译器更快的技术。
从Pentium 5切换到正确数学的芯片......(让我觉得老了的男人......)
我在地上滚来滚去。 Dang - 这太糟糕的人为你降压了!
这是值得的。:)
:)实际上有Pentium 5吗? 如果有,很抱歉它确实有SSE3,因此非常好。 明智地使用时(参见SSE3和FISTTP评论)。
这取决于您是否需要截断转换或舍入转换以及精确度。默认情况下,当您从float转到int时,C将执行截断转换。有FPU指令可以做到这一点,但它不是ANSI C转换,并且使用它有很多警告(例如了解FPU舍入状态)。由于你的问题的答案非常复杂,并且取决于你没有表达的一些变量,我推荐这篇文章:
http://www.stereopsis.com/FPU.html
使用SSE的打包转换是迄今为止最快的方法,因为您可以在同一指令中转换多个值。 ffmpeg有很多组装(主要用于将音频的解码输出转换为整数样本);检查它的一些例子。
这是一个很好的建议,但我会告诉它它假设两件事: - 你有一个带有SSE(> PII)或SSE2(> PIII)的x86处理器 - 你实际上确实想要一个截断,而不是一个舍入,转变
另请注意,这当然不是80位浮点值的选项
普通x86 / x87代码的常用技巧是强制浮点的尾数部分表示int。随后是32位版本。
64位版本是类比的。上面发布的Lua版本更快,但依赖于截断double到32位结果,因此它需要将x87单位设置为双精度,并且不能适用于双到64位int转换。
这个代码的好处是它对于符合IEEE 754的所有平台都是完全可移植的,唯一的假设是将浮点舍入模式设置为最接近。注意:便携式的编译和工作。如果有的话,x86以外的平台通常不会从这种技术中受益很多。
static const float Snapper=3<<22;
union UFloatInt {
int i;
float f;
};
/** by Vlad Kaipetsky
portable assuming FP24 set to nearest rounding mode
efficient on x86 platform
*/
inline int toInt( float fval )
{
Assert( fabs(fval)<=0x003fffff ); // only 23 bit values handled
UFloatInt &fi = *(UFloatInt *)&fval;
fi.f += Snapper;
return ( (fi.i)&0x007fffff ) - 0x00400000;
}
对于无符号整数,它可以更简单:inline uint32_t toInt(float fval){static float const snapper = 1 << 23; fval + = snapper; return((uint32_t)fval)&amp; 0x007FFFFF; }
static float const snapper;使得速度慢于必要。只需写fval += 1<<23;即可
在x86上它并不慢,因为生成的代码是相同的。没有FPU指令在x87上立即参数。
如果可以保证运行代码的CPU与SSE3兼容(即使是Pentium 5,JBB),也可以允许编译器使用其FISTTP指令(即-msse3用于gcc)。它似乎做了应该总是这样做的事情:
http://software.intel.com/en-us/articles/how-to-implement-the-fisttp-streaming-simd-extensions-3-instruction/
请注意,FISTTP与FISTP不同(它有问题,导致速度缓慢)。它是SSE3的一部分,但实际上是(唯一的)X87端的改进。
除此之外,X86 CPU可能会很好地进行转换。 :)
支持SSE3的处理器
Lua代码库有以下代码片段(请访问www.lua.org查看src / luaconf.h)。
如果你发现(SO发现)更快的方式,我相信他们会很激动。
哦,lua_Number意味着加倍。 :)
/*
@@ lua_number2int is a macro to convert lua_Number to int.
@@ lua_number2integer is a macro to convert lua_Number to lua_Integer.
** CHANGE them if you know a faster way to convert a lua_Number to
** int (with any rounding method and without throwing errors) in your
** system. In Pentium machines, a naive typecast from double to int
** in C is extremely slow, so any alternative is worth trying.
*/
/* On a Pentium, resort to a trick */
#if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) && !defined(__SSE2__) && \
(defined(__i386) || defined (_M_IX86) || defined(__i386__))
/* On a Microsoft compiler, use assembler */
#if defined(_MSC_VER)
#define lua_number2int(i,d) __asm fld d __asm fistp i
#define lua_number2integer(i,n) lua_number2int(i, n)
/* the next trick should work on any Pentium, but sometimes clashes
with a DirectX idiosyncrasy */
#else
union luai_Cast { double l_d; long l_l; };
#define lua_number2int(i,d) \
{ volatile union luai_Cast u; u.l_d = (d) + 6755399441055744.0; (i) = u.l_l; }
#define lua_number2integer(i,n) lua_number2int(i, n)
#endif
/* this option always works, but may be slow */
#else
#define lua_number2int(i,d) ((i)=(int)(d))
#define lua_number2integer(i,d) ((i)=(lua_Integer)(d))
#endif
在汇编中有一条指令将浮点转换为int:使用FISTP指令。它将浮点堆栈中的值弹出,将其转换为整数,然后将其存储在指定的地址处。我认为不会有更快的方式(除非你使用像我不熟悉的MMX或SSE这样的扩展指令集)。
另一条指令FIST将值保留在FP堆栈上,但我不确定它是否适用于四字大小的目的地。
我假设需要截断,就像在"C"中写入i = (int)f一样。
如果你有SSE3,你可以使用:
int convert(float x)
{
int n;
__asm {
fld x
fisttp n // the extra 't' means truncate
}
return n;
}
或者,使用SSE2(或在x64中,内联汇编可能不可用),您可以使用几乎同样快:
#include
int convert(float x)
{
return _mm_cvtt_ss2si(_mm_load_ss(&x)); // extra 't' means truncate
}
在较旧的计算机上,可以选择手动设置舍入模式并使用普通的fistp指令执行转换。这可能只适用于浮点数组,否则必须注意不要使用任何会使编译器改变舍入模式的构造(例如转换)。它是这样完成的:
void Set_Trunc()
{
// cw is a 16-bit register [_ _ _ ic rc1 rc0 pc1 pc0 iem _ pm um om zm dm im]
__asm {
push ax // use stack to store the control word
fnstcw word ptr [esp]
fwait // needed to make sure the control word is there
mov ax, word ptr [esp] // or pop ax ...
or ax, 0xc00 // set both rc bits (alternately"or ah, 0xc")
mov word ptr [esp], ax // ... and push ax
fldcw word ptr [esp]
pop ax
}
}
void convertArray(int *dest, const float *src, int n)
{
Set_Trunc();
__asm {
mov eax, src
mov edx, dest
mov ecx, n // load loop variables
cmp ecx, 0
je bottom // handle zero-length arrays
top:
fld dword ptr [eax]
fistp dword ptr [edx]
loop top // decrement ecx, jump to top
bottom:
}
}
请注意,内联汇编仅适用于Microsoft的Visual Studio编译器(也许是Borland),它必须重写为GNU程序集才能使用gcc进行编译。
然而,具有内在函数的SSE2解决方案应该是非常便携的。
其他舍入模式可以通过不同的SSE2内在函数或通过手动将FPU控制字设置为不同的舍入模式来实现。
重新内联汇编:是的Embarcadero(以前的Borland)确实支持它(C ++和Delphi编译器都支持它)
由于MS在X64中使我们脱离内联汇编并迫使我们使用内在函数,因此我查找了要使用的内容。 MSDN doc给出_mm_cvtsd_si64x一个例子。
这个例子有效,但效率非常低,使用2个双倍的未对齐加载,我们只需要一个加载,因此摆脱了额外的对齐要求。然后产生了许多不必要的负载和重新加载,但它们可以如下消除:
#include
#pragma intrinsic(_mm_cvtsd_si64x)
long long _inline double2int(const double &d)
{
return _mm_cvtsd_si64x(*(__m128d*)&d);
}
结果:
i=double2int(d);
000000013F651085 cvtsd2si rax,mmword ptr [rsp+38h]
000000013F65108C mov qword ptr [rsp+28h],rax
可以在没有内联汇编的情况下设置舍入模式,例如,
_control87(_RC_NEAR,_MCW_RC);
舍入到最近的是默认值(无论如何)。
我想,是否要在每次通话中设置舍入模式或假设它将被恢复(第三方库)的问题必须通过经验来回答。
您必须为_control87()和相关常量包含float.h。
并且,不,这不会在32位中工作,因此请继续使用FISTP指令:
_asm fld d
_asm fistp i
这很有意思,似乎是正确的,但在我的测试中,x64编译器实际上为您的代码和MSDN示例生成完全相同的代码(使用反汇编程序验证)。
如果你真的关心它的速度,请确保你的编译器正在生成FIST指令。在MSVC中,您可以使用/ QIfist执行此操作,请参阅此MSDN概述
您还可以考虑使用SSE内在函数为您完成工作,请参阅英特尔的这篇文章:http://softwarecommunity.intel.com/articles/eng/2076.htm
通常,您可以信任编译器高效且正确。通常可以通过为编译器中已存在的东西滚动自己的函数来获得任何东西。
你是完全错误的。在这种情况下,滚动自己的内容比内置函数提高了10倍的速度,因为当你自己动手时,你可以信任内置_ftol不能做的FPU标志的状态,或者你可以使用它来并行化SSE。
或者您可以标记'-msse3'(gcc)并使'固定'FTSTTP正确无误地执行。
编译器提供的例程不适合性能至关重要的多媒体应用程序
c#语言float转换int,关于C#:在x86上将float转换为int的最快方法是什么相关推荐
- java byte转成int数组_Java任意长度byte数组转换为int数组的方法
前言 嗯.最近工程上遇到一个byte数组转换为int的问题,解决过程中遇到了几个坑,经过各种查资料终于还是解决了.撒花. Java的位运算以及byte数组与其他类型数据的转换比c/c++感觉麻烦一些. ...
- java byte数组转int数组_Java任意长度byte数组转换为int数组的方法
前言 嗯.最近工程上遇到一个byte数组转换为int的问题,解决过程中遇到了几个坑,经过各种查资料终于还是解决了.撒花. Java的位运算以及byte数组与其他类型数据的转换比c/c++感觉麻烦一些. ...
- python把object转换成int_python – Pandas:将dtype’object’转换为int
我已经在Pandas中读取了一个SQL查询,并且这些值以dtype'object'形式出现,尽管它们是字符串,日期和整数.我能够将日期'对象'转换为Pandas datetime dtype,但是在尝 ...
- c语言uint赋值给int,如何在C#中将uint转换为int?
假设您只想从一种类型中提取32位并将其原样转储到另一种类型中: uint asUint = unchecked((uint)myInt); int asInt = unchecked((int)myU ...
- c语言 map转换成字符串数组,JSON数组形式字符串转换为ListMapString,String的几种方法...
json转map通用方法 这里提供一方法,可以当作工具类,只要json字符串没有问题,嵌套几层都可以. import net.sf.json.JSONArray; import net.sf.json ...
- c语言printf char数组,在C中输出二维char数组的最快方法
由于您不使用真正的格式,并且只打印单个字符,您可以使用简单的putchar()函数: for (y = 0; y < MAX_Y ; y++) { putchar ('\t'); for (x ...
- C# ASP.NET 转换为int型的方法 很实用
很多新手在搞c#或者.net开发的时候总会碰到一些小问题,如何知道字符能不能为int型 在这里我写了一个小的函数仅供大家参考: /// <summary>/// 判断是不是int型/// ...
- 在C ++中将字符串转换为int
In this article, we will look at how we can convert a string to int in C++. Often, we may need to co ...
- 将Python字符串转换为Int,将Int转换为String
In this tutorial, we will learn how to convert python String to int and int to String in python. In ...
最新文章
- BERT大火却不懂Transformer?读这一篇就够了 重点 命名实体识别
- struts2提交list
- python学习心得--编码格式篇
- 创建一个纯色的背景图
- python表单处理_python flask 表单处理Flask-WTF
- javascript复制到黏贴板之完美兼容
- RedisDesktopManager的安装与使用
- 怎么看电脑配置高不高_辣椒产量高不高?关键看播种前的种子处理,你知道怎么做吗?...
- 3d 多相机分流_徕卡电影四摄的华为Mate30 Pro到底有多猛?开箱了解一下!
- PMP第六版备考笔记练习题答疑(持续更新)
- win10自带抓包工具_Win10商店抓包工具
- Java多线程+线程池
- 信庭嵌入式工作室-ARM应用技术之体系结构应用(下)
- PPT图片怎么排列?
- android 9.0 c7Pro,透心凉!三星Galaxy C7 Pro上线,还内置热管
- 易买网更多新闻代码_《女神异闻录5》新网站源代码内藏玄机 4月25日有更多情报...
- 项目 - Web地图开发【高德地图API】(一)
- 具名插槽 非具名插槽
- Windows设置/去除C盘的写保护
- PVLAN (Private VLAN)
热门文章
- 《Linux那些事儿之我是USB》我是U盘(29)彼岸花的传说(六)--总结
- html qq下高度,怎么知道iframe内容高度
- 洛谷P3964 [TJOI2013]松鼠聚会 切比雪夫距离转曼哈顿距离
- 利用LightGBM实现天气变化的时间序列预测
- 软件测试真的干不到35岁吗?那咋办呢...我36了...
- 未来刷脸支付是能够占据市场很多的份额
- ue4 怎么修改骨骼动画_【2017 GDC挖坟】守望先锋动画制作管线(下篇)
- 一共有n个人,给定m对好友关系,好友的好友也算一个朋友圈,问n个人中一共有几个朋友
- Python3——青蛙跳台阶问题
- 如何才能成功的创业,创业成功的本质是什么