1

我使用 F64 作为元素创建了一个分配,因为我需要 64 位精度进行计算:

Allocation mOutAllocation = Allocation.createSized(mRS,Element.F64(mRS),1,Allocation.USAGE_SCRIPT);

我试图在调用 mScript.forEach_root(mOutAllocation) 后取回结果。通常,您通常会将 mOutAllocation 复制到一个数组并处理该数组,但 double 不是可用的数组类型之一(只有 bytes[]、int[]、float[]、short[] 和 bitmap)。

mScript.forEach_root(mOutAllocation);
    double[] x = new double[1];

    mInAllocation.copyTo(x);

请问有什么想法吗?

4

2 回答 2

2

如果您只需要double在 RenderScript 上下文中复制一个,您可以声明一个非静态变量并使用自动生成的 getter/setter:

// whatever.rs
double hopper;
void root(const double *in, //...
// Whatever.java
mScript = new ScriptC_whatever(mRS);
double hopper = 1.234;
mScript.set_hopper(hopper);

如果需要完整分配,可以使用 NIO 将双精度数组编码为字节数组。然后,您可以使用 . 将它们复制到分配中copyFromUncheced。我不知道如何以编程方式查询 RenderScript 上下文中的字节顺序——我发现我的需要通过反复试验来逆转。

// whatever.rs
double *target;
void root(const double *in, //...
// Whatever.java
public void copyDoublesTo(double[] entries, Allocation target) 
    throws IOException {

    if (!target.getType().getElement().isCompatible(Element.F64(mRS))) 
        throw new RSRuntimeException("Type mismatch: Element != F64");
    if (target.getType().getCount() != entries.length) 
        throw new RSRuntimeException("Type mismatch: wrong # of entries");

    mScript.bind_target(target);

    ByteArrayOutputStream bytes = new ByteArrayOutputStream(Double.SIZE * dim);
    DataOutputStream longs = new DataOutputStream(bytes);
    long temp;
    for(int i=0; i!=dim; ++i) {
        temp = Double.doubleToLongBits(entries[i]);

        // reverse byte order:
        temp = Long.reverseBytes(temp);

        longs.writeLong(temp);
    }

    target.copyFromUnchecked(bytes.toByteArray());
}

您还可以Allocation通过将其绑定到指针然后循环遍历您的数组来初始化您的double,设置每个条目:

// whatever.rs
double *target;
void setTargetEntry(int index, double entry) {
    target[index] = entry;
}
void root(const double *in, //...
public void copyDoublesTo(double[] entries, Allocation target) {
    if (!target.getType().getElement().isCompatible(Element.F64(mRS))) {
        throw new RSRuntimeException("Type mismatch: Element != F64");
    }
    if (target.getType().getCount() != entries.length) {
        throw new RSRuntimeException("Type mismatch: wrong # of entries");
    }
    mScript.bind_target(target);
    for(int i=0; i!=entries.length; ++i) {
        mScript.invoke_setTargetEntry(i, entries[i]);
    }
}

如果您需要double2或类似的,只需在 Java 中交换double即可Double2 。这比其他依赖于...创意打包方案的解决方案更自然地解决了您的问题,因此 RenderScript 将为您解决诸如字节顺序之类的讨厌问题。但是,它需要在分配上进行串行循环,这很 (并且您需要另一个来获取数据)。作为比较,当我测试这个复制 2^10 时float平均 30 毫秒,而本机 copyTo方法只需要 0.1 毫秒。(NIO方法大约需要2ms)

于 2013-11-01T00:01:11.137 回答
2

你能把它读成 long 并将这些位转换为 double 吗?

假设您不需要字节交换,Double.longBitsToDouble(long bits) 应该进行转换。

它需要很长的时间(64 位)并将该位模式解释为 IEEE 双精度。

编辑:尝试将此从 int[] 转换为 long

int[] ints = new int[]{0x01234567, 0x89abcdef};
long l = (long)ints[0] + ((long)ints[1])<<32;
double d = Double.longBitsToDouble(l);
于 2013-07-04T00:38:13.223 回答