有啥方法可以避免 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*' 不匹配