Листинг 7. Перемножение матриц с применением неровных массивов
using System; using System. Diagnostics; using PerfCounter;
namespace BenchJaggedMatrix { /// <summary> /// Перемножение матриц с использованием неровных массивов /// </summary> class MatrixMul {
[ STAThread ] static void Main ( string [] args ) { int i, n;
// Объявляем неровные матрицы double [][] MatrixA, MatrixB, MatrixC; Random r = new Random ( 50 ); n = 1000;
MatrixA = new double [ n ][]; MatrixB = new double [ n ][]; MatrixC = new double [ n ][];
/* Создаем экземпляры массивов и инициализируем их */ for ( i = 0; i <MatrixA. Length; i ++) { MatrixA [ i ] = new double [ n ]; MatrixB [ i ] = new double [ n ]; MatrixC [ i ] = new double [ n ]; for ( int j = 0; j <MatrixA [ i ]. Length; j ++) { MatrixA [ i ][ j ]=( double ) r. Next ( 50 ); MatrixB [ i ][ j ]=( double ) r. Next ( 50 ); } } Counter counter = new Counter ();
/* Вызов и замер времени выполнения Matdot */ Console. WriteLine ( "Starting counter..." ); counter. Reset (); counter. Start (); Matdot ( MatrixA, MatrixB, MatrixC ); // вызов MatDot counter. Stop ();
Console. WriteLine ( "Time taken: {0}", counter ); Console. WriteLine ( "Obtained {0:F2} MFlops", counter. MFlops ( 2 * n * n * n )); Console. ReadLine (); }
public static void Matdot ( double [][] a, double [][] b, double [][] c ) { int i,j,k; double tmp;
for ( i = 0; i <a. Length; i ++) { for ( j = 0; j <c [ i ]. Length; j ++) { tmp = c [ i ][ j ]; for ( k = 0; k <b [ i ]. Length; k ++) { tmp += a [ i ][ k ]* b [ k ][ j ]; } c [ i ][ j ]= tmp; } } } } }
Листинг 8. Перемножение матриц с применением прямоугольных массивов using System; using System. Diagnostics; using PerfCounter;
namespace BenchRectMatrix { /// <summary> /// Перемножение матриц с использованием прямоугольных массивов /// </summary> class MatrixMul {
[ STAThread ] static void Main ( string [] args ) { int i, n;
// Объявляем прямоугольные матрицы double [,] MatrixA, MatrixB, MatrixC; Random r = new Random ( 50 ); n = 1000;
MatrixA = new double [ n,n ]; MatrixB = new double [ n,n ]; MatrixC = new double [ n,n ];
/* Инициализируем случайными значениями */ for ( i = 0; i <n; i ++) { for ( int j = 0; j <n; j ++) { MatrixA [ i,j ]=( double ) r. Next ( 50 ); MatrixB [ i,j ]=( double ) r. Next ( 50 ); } }
Counter counter = new Counter ();
/* Вызов и замер времени выполнения Matdot */ Console. WriteLine ( "Starting counter..." ); counter. Reset (); counter. Start (); Matdot ( n, MatrixA, MatrixB, MatrixC ); // вызов MatDot counter. Stop ();
Console. WriteLine ( "Time taken: {0}", counter ); Console. WriteLine ( "Obtained {0:F2} MFlops", counter. MFlops ( 2 * n * n * n )); Console. ReadLine (); }
public static void Matdot ( int n, double [,] a, double [,] b, double [,] c ) { int i,j,k; double tmp;
for ( i = 0; i <n; i ++) { for ( j = 0; j <n; j ++) { tmp = c [ i,j ]; for ( k = 0; k <n; k ++) { tmp += a [ i,k ] * b [ k,j ]; } c [ i,j ]= tmp; } } } } }
Выполнение этих двух программ на моей тестовой машине дало результаты, показанные на рис. 3. Результаты могут быть еще лучше, если преобразовать многомерные массивы в одномерные. Если вас не заботит синтаксис, это тривиально: просто используйте один индекс как смещение. Например, ниже объявляется одномерный массив для использования вместо двухмерного:
Листинг 9.
double [] myArray = new double [ ROW_DIM * COLUMN_DIM ];
Рис. 3. Неровные массивы против прямоугольных
Для индексации элементов в таком массиве указывайте следующее смещение:
|