将float数组比较为int数组

时间:2015-07-31 21:49:26

标签: c++ c floating-point floating-point-conversion

我需要对已排序数字的数组进行优化的二进制搜索算法。我做了这个,发现使用float来存储数字比使用整数更快,因为最后我必须计算

(frameNumber-this->frameNumber[imin])/(this->frameNumber[imax]-this->frameNumber[imin])

this->frameNumber[imin]是最小的frameNumber,不等于frameNumberthis->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转换为浮点数不是那么算,或者浮点数之间的比较与整数一样快?

非常感谢!

1 个答案:

答案 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那么快的浮点数,所以不要过分浮点。