1

我有一个大致如下所示的类:

template<std::size_t dim>
class Foo {
public:
    Foo(void const * const data);
private: 
    double vals[dim];
}

对于构造函数,我知道它void* data指向一个float值数组(维度暗淡)。现在我想vals在该构造函数的初始化列表中初始化 -array (最好)。

更糟糕的是,指向的浮点数不一定必须正确对齐内存。

我怎样才能有效地做到这一点?


编辑 1

关于下面发生的讨论,让我先说明我的设计优先事项。这可能会帮助您专注于对我来说最重要的问题。

  1. 应对糟糕的内存对齐
  2. 在性能方面获得尽可能少的操作。

老实说,如果我们需要构造函数体来获得快速算法的工作,这对我来说也很好。重点是原始功率。

4

4 回答 4

1

如果您担心传递的指针未与float边界对齐(例如,文件映射等),那么您可以编写类似

template<std::size_t dim>
class Foo {
public:
    Foo(void const * const data)
    {
        float temp[dim];
        memcpy( &temp, data, dim * sizeof( float ) );
        std::copy( temp, temp + dim, vals );
    }
private: 
    double vals[dim];
}

可能是一个过分热心且不太便携的解决方案:

template<std::size_t dim>
class Foo {
public:
    Foo(void const * const data)
    {
        if( static_cast<long>( data ) % sizeof( float ) == 0 ) {
            const float *temp = data;
            std::copy( temp, temp + dim, vals );
        } else {
            float temp[dim];
            memcpy( &temp, data, dim * sizeof( float ) );
            std::copy( temp, temp + dim, vals );
        }
    }
private: 
    double vals[dim];
}

在初始化器列表中初始化不会使您的代码更快,它只是在可能的情况下提供便利。

如果您非常关心性能,我会将其包装if在一个宏中,并且仅if在需要正确对齐访问的架构上使用(x86 不是一个,它只是在 x86 上速度较慢)。

编辑

感谢 Steve Jessop在评论中提出的另一个解决方案。它侧重于减少临时变量的大小。

double *dest = vals;
float tmp;
void const *first = data;
void const *last = data + dim * sizeof(float);
while( first != last ) {
    memcpy( &tmp, first, sizeof(float) );
    first += sizeof(float);
    *dest++ = tmp;
}

可能需要进行一些微基准测试/分解。

于 2011-07-26T11:55:49.853 回答
0

您不能在当前 C++ 标准中初始化初始化列表中的数组。您可以利用事先知道尺寸的事实来使用std::vector

template<std::size_t dim>
class Foo {
public:
  Foo(float const * const data) : vals(dim) // fix the vector size
  {
    for(std::size_t i=0; i<dim; i++)
      vals[i] = data[i];  // assignment
  }
private: 
  std::vector<double> vals;
};

我不能争辩说它vector<>与原始数据一样有效。但是它们经过了很好的优化并且异常安全。

于 2011-07-26T11:34:23.897 回答
0

因为float与 大小不同double,我认为唯一的方法是从一个数组手动分配到另一个数组。

是否可以更改vals为数组float?这将允许您data使用memcpy. float因为在将s 存储在double数组中时不会获得精度,除非您vals稍后更改为使用 的高精度,否则您double不会从使用doubles 中获得任何好处。

于 2011-07-26T11:23:09.773 回答
0

为什么要隐藏类型?

这有什么问题:

template<std::size_t dim>
class Foo {
public:
    Foo(float const * const data);
private: 
    double vals[dim]
}

template<std::size_t dim>
Foo< dim >::Foo(float const * const data) : vals()
{
  std::copy( data, data+dim, &vals[0] );
}

编辑

如果你切换到std::vector,你可以像这样初始化:

class Foo {
public:
    Foo(float const * const dataBegin,float const * const dataEnd);
private: 
    std::vector< double > vals;
}

Foo::Foo(float const * const dataBegin,float const * const dataEnd) : vals( dataBegin, dataEnd )
{
}
于 2011-07-26T11:23:36.393 回答