有啥方法可以避免 valarray 和数组之间的复制吗?

Posted

技术标签:

【中文标题】有啥方法可以避免 valarray 和数组之间的复制吗?【英文标题】:is there any way to avoid the copy from and to between the valarray and array?有什么方法可以避免 valarray 和数组之间的复制吗? 【发布时间】:2011-07-27 16:24:19 【问题描述】:

我在一个列表中有很多数据,比如每个元素有几个 kbytes,我想逐个提取每个元素来进行一些数值处理。这些数据最初存储为 float[]。由于处理涉及大量索引和全局计算,我认为 valarray 可能易于编程。但是如果我使用 valarray,我可能必须先从数组复制到 valarray,然后再复制回数组。有没有办法避免这种情况?有什么方法可以让我直接在数组上工作吗?或者你有更好的方法来解决类似的问题?

【问题讨论】:

您要解决的实际问题是什么? @tomalak:只想处理大量存储在内存中的列表中的数据。列表中的每个元素都是一个数据结构或一个类。处理主要涉及对数据结构内部数组中的全部或部分值进行数值计算。希望我这次说清楚。 我完全不明白这个问题。也许我只是太厚了。 @Tomalak,我觉得尚平有一个普通的数组,但是想使用valarray提供的一些操作。为此,需要将普通数组中的所有数据复制到 valarray 中。问题是如何避免复制。 与您正在进行的数字处理的成本相比,副本的成本是否显着?你量过吗? 【参考方案1】:

valarray 类型不提供将现有数组用于其数据存储的任何方式;它总是为自己制作副本。不要将数据存储在普通数组中,而是从一开始就将值直接存储在valarray 中。调用v.resize 设置大小,然后使用[] 运算符为其赋值,或者使用&v[0] 获取指向第一个值的指针,并像使用迭代器或缓冲区指针一样使用它——a 的元素valarray 连续存储在内存中。

【讨论】:

谢谢,我明白你的意思。问题是我无法更改之前涉及太多更改的阵列设计。【参考方案2】:

警告:丑陋的黑客攻击

在我的系统(MS Visual Studio)上,valarray 类的定义如下:

template<class _Ty>
class valarray

    ...
private:
    _Ty *_Myptr;    // current storage reserved for array
    size_t _Mysize; // current length of sequence
    size_t _Myres;  // length of array
;

所以我可以构建自己的具有相同布局的类(具有良好的信心):

struct my_valarray_hack

    void *_Myptr;
    size_t num_of_elements;
    size_t size_of_buffer;
;

然后创建一个空的valarray 并覆盖其内部变量,使其指向您的数据。

void do_stuff(float my_data[], size_t size)

    valarray<float> my_valarray;
    my_valarray_hack hack = my_data, size, size;
    my_valarray_hack cleanup;

    assert(sizeof(my_valarray) == sizeof(hack));

    // Save the contents of the object that we are fiddling with
    memcpy(&cleanup, &my_valarray, sizeof(cleanup));

    // Overwrite the object so it points to our array
    memcpy(&my_valarray, &hack, sizeof(hack));

    // Do calculations
    ...

    // Do cleanup (otherwise, it will crash)
    memcpy(&my_valarray, &cleanup, sizeof(cleanup));
    // Destructor is silently invoked here

不是推荐的做事方式;仅当您没有其他方法可以实现您想要的东西时(甚至那时可能没有),您才应该考虑它。失败的可能原因:

valarray 的布局在另一种编译模式下可能会有所不同(模式示例:调试/发布;不同平台;不同版本的标准库) 如果您的计算以任何方式调整 valarray 的大小,它将尝试重新分配您的缓冲区并崩溃 如果valarray 的实现假定其缓冲区具有例如16 字节对齐,它可能会崩溃、计算错误或运行缓慢(取决于您的平台) (我相信还有其他一些原因导致它不起作用)

无论如何,它被标准描述为“未定义的行为”,所以严格来说,如果您使用此解决方案,任何事情都可能发生。

【讨论】:

以上是关于有啥方法可以避免 valarray 和数组之间的复制吗?的主要内容,如果未能解决你的问题,请参考以下文章

gcc和msvc(或Linux和Windows)中的valarray有啥区别

Valarray 切片数组与 'operator*' 不匹配

缓存和记忆有啥区别?

valarray vs. vector:为啥要引入 valarray?

Scala:将元素附加到数组的最佳方法是啥?

对于所提供的用例,微服务和单一方法之间有啥区别