Мне нужно пробовать огромную случайную матрицу, размер которой 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
реализуется как 1D std::vector
для эффективности.
Могу ли я сделать это лучше? Прямо сейчас, выборка этой огромной матрицы занимает приблизительно 0,16 секунды.
EDIT с помощью 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;
}
Все, кажется, работайте отлично, но я не получил ничего хорошего.
Другие двигатели могут быть быстрее, чем mersenne twister. Вы можете разбить матрицу ('std :: vector') на блоки и заполнить их параллельно. Убедитесь, что 'Matrix' имеет конструктор перемещения (потому что вы возвращаете его, и копия можно было бы избежать). – Aleph
@Aleph Спасибо за ваши предложения! На самом деле я не думал об изменении движка: я попробую. Я также понимаю, что распараллеливание алгоритма сделает вещи быстрее, но я не понимаю, что вы сказали о конструкторах перемещения ... Я не думаю, что у меня есть один прямо сейчас – minomic
В моих тестах в моей системе версия '64bit' твистер несколько медленнее, чем обычная версия «32bit». Я вижу, что вы допускаете большой диапазон для модуля в параметре функции, но ваш дистрибутив создается с помощью 'int' по умолчанию. В противном случае вы можете получить некоторую выгоду от установки функции back-door в вашей матрице, обеспечивающей доступ к плоскому вектору. – Galik