我需要对已排序数字的数组进行优化的二进制搜索算法。我做了这个,发现使用float来存储数字比使用整数更快,因为最后我必须计算
(frameNumber-this->frameNumber[imin])/(this->frameNumber[imax]-this->frameNumber[imin])
this->frameNumber[imin]
是最小的frameNumber,不等于frameNumber
和this->frameNumber[imax]
是大于等于的最小的void binary_search(float key,float* array,...)
{
int key_integer=*(int*)&key;
int* array_intege(int*)array;
binary_search_for_integers(key_integer,array_integer,...);
}
。该代码用于计算两个关键帧之间的进度。
frameNumber数组是静态的。我只需要对它进行一次排序。但是使用二进制搜索和上面的代码可以多次访问它来计算进度。
从int到float的转换花费了一些周期。 然后我发现在asm中有很多fpu指令。我担心它们可能比整数慢。
所以这就是问题所在。我可以将已排序的浮点数数组转换为int *并对其进行二进制搜索吗?
这意味着:
public abstract class JavascriptFunction<TFunction, TDelegate> where TFunction : JavascriptFunction<TFunction, TDelegate>, new()
{
private static TFunction instance = new TFunction();
private static string name = typeof(TFunction).Name;
private string functionBody;
protected JavascriptFunction(string functionBody) { this.functionBody = functionBody; }
public static string Call(Expression<Action<TDelegate>> func)
{
return instance.EmitFunctionCall(func);
}
public static string EmitFunction()
{
return "function " + name + "(" + extractParameterNames() + ")\r\n{\r\n " + instance.functionBody.Replace("\n", "\n ") + "\r\n}\r\n";
}
private string EmitFunctionCall(Expression<Action<TDelegate>> func)
{
return name + "(" + this.extractArgumentValues(((InvocationExpression) func.Body).Arguments) + ");";
}
private string extractArgumentValues(System.Collections.ObjectModel.ReadOnlyCollection<Expression> arguments)
{
System.Text.StringBuilder returnString = new System.Text.StringBuilder();
string commaOrBlank = "";
foreach(var argument in arguments)
{
returnString.Append(commaOrBlank + this.getArgumentLiteral(argument));
commaOrBlank = ", ";
}
return returnString.ToString();
}
private string getArgumentLiteral(Expression argument)
{
if (argument.NodeType == ExpressionType.Constant) return this.getConstantFromArgument((ConstantExpression) argument);
else return argument.ToString();
}
private string getConstantFromArgument(ConstantExpression constantExpression)
{
if (constantExpression.Type == typeof(String)) return "'" + constantExpression.Value.ToString().Replace("'", "\\'") + "'";
if (constantExpression.Type == typeof(Boolean)) return constantExpression.Value.ToString().ToLower();
return constantExpression.Value.ToString();
}
private static string extractParameterNames()
{
System.Text.StringBuilder returnString = new System.Text.StringBuilder();
string commaOrBlank = "";
MethodInfo method = typeof(TDelegate).GetMethod("Invoke");
foreach (ParameterInfo param in method.GetParameters())
{
returnString.Append(commaOrBlank + param.Name);
commaOrBlank = ", ";
}
return returnString.ToString();
}
}
public abstract class CoreJSFunction<TFunction, TDelegate> : JavascriptFunction<TFunction, TDelegate>
where TFunction : CoreJSFunction<TFunction, TDelegate>, new()
{
protected CoreJSFunction() : base(null) {}
}
或者我的上述结论是错误的? (比如将int转换为浮点数不是那么算,或者浮点数之间的比较与整数一样快?
非常感谢!
答案 0 :(得分:4)
这似乎是一个坏主意。正如@rlbond指出的那样,对浮点数据使用整数比较实际上将导致正确排序的浮点数组。 (请参阅http://www.h-schmidt.net/FloatConverter/IEEE754.html以使用浮点数的二进制表示。)在使用之前检查sizeof(int32_t) == sizeof(float)
。
这样的黑客并不是真的需要。 float
比较并不比现代硬件上的int
比较贵得多。 (Intel Haswell:ucomiss
是1 uop,每个周期吞吐量为1。与内存操作数相比,2 uop,没有微融合。并且它不能像cmp/jcc
那样宏融合但是, FP add / sub和FP mul具有比其整数等值更高的延迟,并且吞吐量更低。将整个数组转换为float
似乎很愚蠢,只是因为你想在最后用最小值和最大值做一些FP数学。
load-and-convert-int-to-float指令(x86 cvtsi2ss
(带符号整数2标量单))的速度与正常负载一样快,并且占用相同的代码空间({ {1}})。
如果您的数据最初是整数,而您只使用其中的一部分,请使用movss
(避免转换您以后永远不需要的值)。如果您确实访问了所有数据,并且只将数据用作浮点数,则将其存储为int
。如果你将它作为两者使用,最好将它存储为float
,因此当你将它用作整数时它会更快,并且当你将它用作float时,速度大致相同。
从您的代码示例中,您只是使用最小和最大位置的值?找到数组中的最小值和最大值要比对整个数组进行排序要快得多。 min / max均使用压缩最小指令进行矢量化。
许多平台没有现代Intel CPU那么快的浮点数,所以不要过分浮点。