对均匀随机矩阵进行高效采样

Efficiently sampling a uniform random matrix

本文关键字:高效 采样 随机      更新时间:2023-10-16

我需要采样一个巨大的随机矩阵,其大小为 499 x 15500 ,即 7734500元素。出于这个原因,我希望抽样程序尽可能有效。目前,在 cpp 文件中,我正在这样做:

std::random_device rd; // seed generator
std::mt19937_64 generator{rd()}; // generator initialized with seed from rd

std::uniform_int_distribution<> initialize(unsigned long long int modulus)
{
    std::uniform_int_distribution<> unifDist{0, (int)(modulus-1)};
    return unifDist;
}

Matrix<unsigned int> uniformRandomMatrix
    (unsigned int rows, unsigned int columns, unsigned long long int modulus)
{
    std::uniform_int_distribution<> dist = initialize(modulus);
    // Declare and allocate the matrix
    Matrix<unsigned int> matrix(rows, columns);
    // this constructor just does a resize on a std::vector
    // Fill the matrix with random elements
    for(unsigned int i = 0; i < rows; ++i)
    {
        for(unsigned int j = 0; j < columns; ++j)
        {
            matrix.setElementAt(i, j, dist(generator));
            // setElementAt just does matrix[somePosition] = newElement
        }
    }
    return matrix;
}

请注意,为了提高效率,Matrix是作为一维std::vector实现的。

我能做得比这更好吗?现在,对这个巨大的矩阵进行采样大约需要0.16秒。

使用std::vector::data编辑

新方法是这样的:我在Matrix类中添加了一个方法

inline std::vector<T> exposeVector()
{
    return matrix;   // 'matrix' is the name of the private std::vector
}

然后取样制服Matrix

Matrix<unsigned int> uniformRandomMatrix
    (unsigned int rows, unsigned int columns, unsigned long long int modulus)
{
    std::uniform_int_distribution<> dist = initialize(modulus);
    // Declare and allocate the matrix
    Matrix<unsigned int> matrix(rows, columns);
    std::vector<unsigned int> v = matrix.exposeVector();
    unsigned int* p = v.data();
    for(unsigned int i = 0 ; i < rows*columns ; ++i)
    {
        *p = dist(generator);
        ++p;
    }
    return matrix;
}

一切似乎都很好,但我在性能方面没有获得任何好处。

在我看来,这是一个相当广泛的问题,但我会尝试给你一些指示:

  • 首先,也可能是最明显的事情是在多个线程中执行此操作std::thred
  • 如果你的矩阵是一个派生类,而你的setElementAt是虚拟的,那么由于 vtable 解析,它的成本真的很高。摆脱它(见下一行)
  • 通常编译器已经做了很多优化,但你仍然可以尝试最小化函数/方法调用,通过公开你的vector::d ata并迭代为单个数组for(int i = 0; i < rows*cols; i++); data[i] = random或尝试std::generate。