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

发布于 2024-11-26 09:50:55 字数 205 浏览 2 评论 0原文

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

I have a lot of data in a list, say several kbytes in each element, I would like to extract each by each to do some numeric processing. These data are originally stored as float[]. Since the processing involves a lot of indexing and global calculation, I think valarray might be easy to program. But if I use valarray, I may have to copy from the array to the valarray first, and then copy back to the array. Is there any way to avoid this? Any way such that to let me work directly on the arrays? Or do you have better ways to solve similar problems?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

岁吢 2024-12-03 09:50:55

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

The valarray type does not provide any way to use an existing array for its data store; it always makes a copy for itself. Instead of storing your data in an ordinary array, store the values directly in the valarray from the start. Call v.resize to set the size, and either assign values into it with the [] operator, or use &v[0] to get a pointer to the first value and use it as you would an iterator or buffer pointer — elements of a valarray are stored contiguously in memory.

橘寄 2024-12-03 09:50:55

警告:丑陋的黑客行为

在我的系统(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 字节对齐,它可能会崩溃,执行错误的计算或只是工作缓慢(取决于您的平台)
  • (我确信还有更多原因导致它不起作用)

无论如何,标准将其描述为“未定义行为”,因此严格来说,如果您使用此解决方案,则可能会发生任何情况。

Warning: ugly hack.

On my system (MS Visual Studio) the valarray class is defined like this:

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
};

So i can build my own class that has the same layout (with a good level of confidence):

struct my_valarray_hack
{
    void *_Myptr;
    size_t num_of_elements;
    size_t size_of_buffer;
};

Then create an empty valarray and overwrite its internal variables so it points to your data.

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
}

This is not a recommended way of doing things; you should consider it only if you have no other way to implement what you want (maybe not even then). Possible reasons why it could fail:

  • Layout of valarray may be different in another mode of compilation (examples of modes: debug/release; different platforms; different versions of Standard Library)
  • If your calculations resize the valarray in any manner, it will try to reallocate your buffer and crash
  • If the implementation of valarray assumes its buffer has e.g. 16-byte alignment, it may crash, do wrong calculations or just work slowly (depending on your platform)
  • (I am sure there are some more reasons for it not to work)

Anyway, it's described as "undefined behavior" by the Standard, so strictly speaking anything may happen if you use this solution.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文