0

すべてのデータが連続するように 3 次元行列を格納したいと考えています。これは、MPI を使用してマトリックスをマスター ノードに送信し、すべての小さなマトリックスを 1 つの大きなマトリックスに連結する必要があるためです。複数の int や double などをメモリ内で連続している場合にのみ送信できるため、ネストされたベクトルでは面倒です。

for (int i = 0; i < nx; i++) {
    for (int j = 0; j < ny; j++) {
        int id_of_data = i*ny*nz + j*nz;
        MPI_Send(&local_matrix[i][j][0], nz, MPI_DOUBLE, 0, id_of_data, MPI_COMM_WORLD);
    }
}

次に、マスターノードでデータを受信します。id_of_data 現在、マトリックスを格納するために標準ベクトルを使用しています。

std::vector<std::vector<std::vector<double> > > matrix;

だから私は今のところ std::vector に固執しようとしています。配列/ポインターを使用してこれを簡単に解決できることはわかっていますが、それに頼る前に std::vectors を使用してこれを試してみたいと思います。行列の次元は一定であるため、動的割り当てについて心配する必要はありません。

このようなポインターを使用して、ベクターの要素にアクセスできます

double* a = &matrix[x][y][z];

しかし、「反対」を行う方法がわかりません。何かのようなもの

double* vec_ptr = new float(nz);
&matrix[x][y][0] = vec_ptr;

私がやりたいことは

double* linear_matrix = new double(nx*ny*nz);

そして、ネストされたベクトルがこのデータを指すようにします。

4

1 に答える 1

0

この種の状況のた​​めに独自のクラスを作成することになりました。行列操作ライブラリが行列をデータの連続ブロックとして受け取ることは非常に一般的ですが、同時に、標準の m[i][j] アクセサーを使用してそれを埋めて読み取ることができるようにしたいと考えています。では、どうぞ。以下は、メモリの連続ブロックとして任意の次元でコンテナーを作成するコードです。ここでブースト プリプロセッサを使用して、任意のディメンションを実行できるようにします。3Dまでしか必要ない場合は、ブーストを解除するのは明らかです:)

memblock.h

#ifndef BOOST_PP_IS_ITERATING

#ifndef MEMBLOCK_INCLUDED
#define MEMBLOCK_INCLUDED
#include <algorithm>
#include <boost/preprocessor.hpp>

#    ifndef MBLOCK_MAX_DIM
#      define MBLOCK_MAX_DIM 4
#    endif

template <typename T> class MemoryBlock1d
{
protected:
    T* m_data;
public:
    MemoryBlock1d() { m_data = 0; }
    MemoryBlock1d(int size) { m_data = 0;  resize(size); }
    MemoryBlock1d(int size, T val) { m_data = 0;  resize(size, val); }
    virtual ~MemoryBlock1d();
    inline T*& data() { return m_data; }
    inline void resize(int size);
    inline void resize(int size, T val);
    inline void clear();
    inline T& operator[](int i) { return m_data[i]; }
};

// Implementation 1d:
template <typename T> inline MemoryBlock1d<T>::~MemoryBlock1d()
{
    if (m_data)
    {
        delete[] m_data;
    }
}

template <typename T> inline void MemoryBlock1d<T>::clear()
{
    if (m_data)
    {
        delete[] m_data;
    }
    m_data = 0;
}

template <typename T> inline void MemoryBlock1d<T>::resize(int size)
{
    if (m_data)
    {
        delete[] m_data;
    }
    m_data = new T[size];
}

template <typename T> void MemoryBlock1d<T>::resize(int size, T val)
{
    resize(size);
    std::fill(m_data, m_data + size, val);
}


// generate multi_dimensional blocks:
#    define BOOST_PP_ITERATION_LIMITS (2, MBLOCK_MAX_DIM)
#    define BOOST_PP_FILENAME_1       "memblock.h"   // this file
#    include BOOST_PP_ITERATE()

#endif // MEMBLOCK_INCLUDED

#else // BOOST_PP_IS_ITERATING
#   define n BOOST_PP_ITERATION()
#   define nprev BOOST_PP_SUB(n, 1)
#   define MemoryBlockNd BOOST_PP_CAT(MemoryBlock, BOOST_PP_CAT(n, d))
#   define MemoryBlockPREVd BOOST_PP_CAT(MemoryBlock, BOOST_PP_CAT(nprev, d))
#   define MB_print(z, m, data) data
#   define MB_timesDATAM(z, m, data) * BOOST_PP_CAT(data, m)

template <typename T> class MemoryBlockNd : public MemoryBlock1d<T>
{
private:
    MemoryBlockPREVd<T*> m_pointers;
public:
    MemoryBlockNd() { MemoryBlock1d<T>::data() = 0; }
    MemoryBlockNd(BOOST_PP_ENUM_PARAMS(n, int size)) { MemoryBlock1d<T>::data() = 0;  resize(BOOST_PP_ENUM_PARAMS(n, size)); }
    MemoryBlockNd(BOOST_PP_ENUM_PARAMS(n, int size), T val) { MemoryBlock1d<T>::data() = 0;  resize(BOOST_PP_ENUM_PARAMS(n, size), val); }
    inline void resize(BOOST_PP_ENUM_PARAMS(n, int size));
    inline void resize(BOOST_PP_ENUM_PARAMS(n, int size), T val);
    inline T BOOST_PP_REPEAT(nprev, MB_print,*) & operator[](int i) { return m_pointers[i]; }
};

// Implementation n-dim:

template <typename T> void MemoryBlockNd<T>::resize(BOOST_PP_ENUM_PARAMS(n, int size))
{
    m_pointers.resize(BOOST_PP_ENUM_PARAMS(nprev, size));
    int sizePointers = size0 BOOST_PP_REPEAT_FROM_TO(1, nprev, MB_timesDATAM, size);
    int sizeData = sizePointers * BOOST_PP_CAT(size, nprev);
    MemoryBlock1d<T>::resize(sizeData);

    T *p = MemoryBlock1d<T>::data();
    T **ptr = m_pointers.data();

    for (int i=0; i < sizePointers; i++, p += BOOST_PP_CAT(size, nprev)) ptr[i] = p;
}

template <typename T> void MemoryBlockNd<T>::resize(BOOST_PP_ENUM_PARAMS(n, int size), T val)
{
    resize(BOOST_PP_ENUM_PARAMS(n, size));
    int sizeData = size0 BOOST_PP_REPEAT_FROM_TO(1, n, MB_timesDATAM, size);
    std::fill(MemoryBlock1d<T>::data(), MemoryBlock1d<T>::data() + sizeData, val);
}

#  undef MB_timesDATAM
#  undef MB_print
#  undef MemoryBlockPREVd
#  undef MemoryBlockNd
#  undef nprev
#  undef n
#endif // BOOST_PP_IS_ITERATING

memblock.cpp

// test the class here
#include <stdio.h>
#include <memblock.h>

int main() {
  MemoryBlock3d<double> cube(2, 2, 2);
  double *p = &cube[0][0][0];

  for (int i=0; i < 8; i++)
    p[i] = 0.5 + i;

  for (int i=0; i < 2; i++)
    for (int j=0; j < 2; j++)
      for (int k=0; k < 2; k++)
        printf("%f\n", cube[i][j][k]);

  return 0;
}
于 2013-09-08T17:46:06.597 に答える