1

おおよそ次のようなクラスがあります。

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

コンストラクターの場合、それが(次元dimの)値void* dataの配列を指していることを私は知っています。ここで、そのコンストラクターの初期化リストで-arrayを(できれば)float初期化したいと思います。vals

さらに悪いことに、指摘されたフロートは必ずしも適切にメモリ整列されている必要はありません。

どうすればこれを効率的に行うことができますか?


編集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は1つではなく、x86では低速です)。

編集

スティーブジェソップのおかげで、コメントで提案された別の解決策 。一時変数のサイズを減らすことに焦点を当てています。

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

なぜタイプを隠しているのですか?

これの何が問題になっていますか:

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 に答える
0

floatはとはサイズが異なるためdouble、1つの配列から別の配列に手動で割り当てるのが唯一の方法だと思います。

valsの配列に変更することは可能floatですか?dataこれにより、を使用してアレイをコピーできますmemcpyfloatsをdouble配列に格納する際の精度は得られないため、vals後での高い精度を使用するように変更しない限り、sを使用doubleしても何も得られませんdouble

于 2011-07-26T11:23:09.773 に答える
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 に答える