C中的填充矩阵

时间:2016-05-07 21:21:55

标签: c matrix sse transpose

我尝试使用SSE来转置我的矩阵。但它只能拟合N可被4整除的矩阵。所以我想填充矩阵来重新格式化它。

例如,如果是3 * 3矩阵,则应填入4 * 4矩阵:

1 2 3    1 2 3 0 
4 5 6 => 4 5 6 0
7 8 9    7 8 9 0
         0 0 0 0

有效的方法吗?而且我不确定是否花费时间来填充它,SSE转置是否会比仅循环每个索引更慢......

3 个答案:

答案 0 :(得分:1)

你实际上不需要垫,是吗?您只是建议使用您已经拥有的4x4 SSE转置例程,对吧?

矩阵转置不会移动对角线元素(包括第一个和最后一个)。 3x3转置具有更少的数据移动:仅需要加载/存储7个元素。

1 2 3    1 4 7
4 5 6 => 2 5 8
7 8 9    3 6 9

AVX2:

如果您的元素是4B(intfloat,而不是double),则前8个元素适合单个AVX向量。 AVX2有一个完整的车道交叉随机播放vpermps。因此整个转置可以使用单个加载/ _mm256_permutevar8x32_ps /存储来完成。它在Intel Haswell上具有每时钟吞吐量和三个周期延迟。

由于最后一个元素不需要移动,因此您根本不需要触摸它,除非在您没有就地转置时复制它。

只使用SSE,您可以加载包含前八个元素的两个向量,并使用shufps或其他东西将它们相互混合以组合每个向量中的元素。

或者也可以随意创建一个{ 1 4 3 2 }向量和一个{ 5 8 7 6 }向量,然后将元素7混合到第一个,并将元素3混合到第二个。

无论如何,3x3比4x4更容易转置,所以如果你以后不需要在整行上使用SSE,请不要填4x4。

答案 1 :(得分:0)

不,您无法有效填充矩阵。假设平面数组,您需要创建另一个内存区域,然后将值复制到左上角,然后将剩余值设置为零。因此,每个值本身就是一个操作。

您可以做的是从填充矩阵开始并对它们执行所有操作,或使用稀疏矩阵表示。但由于目标是快速移调,因此你可能会在波动中获胜并在环形交叉路口输掉比赛。

答案 2 :(得分:-2)

增加数组或矩阵的大小是一个有趣的问题。我们可以创建一个填充的新数组或矩阵,并将所有内容复制到新的。

#include <stdio.h>
#include <stdlib.h>
#include <histedit.h>
#define MATRIX_SIZE 3 /* use some size */

/* returns an array of arrays of int*, all of which NULL */
int ***alloc_matrix(unsigned rows, unsigned columns) {
    int ***matrix = malloc(rows * sizeof(int **));
    if (!matrix) abort();
    for (unsigned row = 0; row < rows; row++) {
        matrix[row] = malloc(columns * sizeof(int *));
        if (!matrix[row]) abort();
        for (unsigned column = 0; column < columns; column++) {
            matrix[row][column] = NULL;
        }
    }
    return matrix;
}

/* deallocates an array of arrays of int*, calling free() on each */
void free_matrix(int ***matrix, unsigned rows, unsigned columns) {
    for (unsigned row = 0; row < rows; row++) {
        for (unsigned column = 0; column < columns; column++) {
            //    printf("column %d row %d\n", column, row);
            free(matrix[row][column]);
        }
        free(matrix[row]);
    }
    free(matrix);
}

int *** padding_matrix(int ***matrix, unsigned size, unsigned padding) {
    int ***padded_matrix = alloc_matrix(padding, padding);
    for (unsigned row = 0 ; row < size; row++) {
        for (unsigned column = 0 ; column < size; column++) {
            printf("copying column %d row %d %d\n", column, row,  * matrix[row][column]);
            padded_matrix[row][column] =  matrix[row][column];
            printf("copied column %d row %d %d\n", column, row,  * padded_matrix[row][column]);
        }
    }

    for (unsigned row = size ; row < padding; row++) {
        for (unsigned column = 0 ; column < padding; column++) {
            int i = 0;
            padded_matrix[row][column] = &i;
            printf("padded column %d row %d\n", column, row);
        }
    }

    for (unsigned row = 0 ; row < padding; row++) {
            int i = 0;
            padded_matrix[row][3] = &i;
            printf("padded column %d row %d\n", 3, row);
        }
    return padded_matrix;
}

int main(int argc, char *argv[]) {
    int ***matrix = alloc_matrix(MATRIX_SIZE, MATRIX_SIZE);
    int x = 1;
    int y = 2;
    int z = 3;
    int u = 4;
    int w = 5;
    int a = 6;
    int b = 7;
    int c = 8;
    int d = 9;

    matrix[0][0] = &x;
    matrix[0][1] = &y;
    matrix[0][2] = &z;
    matrix[1][0] = &u;
    matrix[1][1] = &a;
    matrix[1][2] = &w;
    matrix[2][0] = &b;
    matrix[2][1] = &c;
    matrix[2][2] = &d;
    for (unsigned row = 0 ; row < MATRIX_SIZE; row++) {
        for (unsigned column = 0 ; column < MATRIX_SIZE; column++) {
            printf("matrix column %d row %d=%d\n", column, row , * matrix[row][column]);
        }
    }


    int ***matrix2  = padding_matrix(matrix, MATRIX_SIZE, MATRIX_SIZE + 1);
    for (unsigned row = 0 ; row < MATRIX_SIZE+1; row++) {
        for (unsigned column = 0 ; column < MATRIX_SIZE+1; column++) {
            printf("padded matrix column %d row %d=%d\n", column, row , * matrix2[row][column]);
        }
    }
}

测试

padmatrix
matrix column 0 row 0=1
matrix column 1 row 0=2
matrix column 2 row 0=3
matrix column 0 row 1=4
matrix column 1 row 1=6
matrix column 2 row 1=5
matrix column 0 row 2=7
matrix column 1 row 2=8
matrix column 2 row 2=9
copying column 0 row 0 1
copied column 0 row 0 1
copying column 1 row 0 2
copied column 1 row 0 2
copying column 2 row 0 3
copied column 2 row 0 3
copying column 0 row 1 4
copied column 0 row 1 4
copying column 1 row 1 6
copied column 1 row 1 6
copying column 2 row 1 5
copied column 2 row 1 5
copying column 0 row 2 7
copied column 0 row 2 7
copying column 1 row 2 8
copied column 1 row 2 8
copying column 2 row 2 9
copied column 2 row 2 9
padded column 0 row 3
padded column 1 row 3
padded column 2 row 3
padded column 3 row 3
padded column 3 row 0
padded column 3 row 1
padded column 3 row 2
padded column 3 row 3
padded matrix column 0 row 0=1
padded matrix column 1 row 0=2
padded matrix column 2 row 0=3
padded matrix column 3 row 0=0
padded matrix column 0 row 1=4
padded matrix column 1 row 1=6
padded matrix column 2 row 1=5
padded matrix column 3 row 1=0
padded matrix column 0 row 2=7
padded matrix column 1 row 2=8
padded matrix column 2 row 2=9
padded matrix column 3 row 2=0
padded matrix column 0 row 3=0
padded matrix column 1 row 3=0
padded matrix column 2 row 3=0
padded matrix column 3 row 3=0

Process finished with exit code 0

您在上面的输出中看到填充矩阵较大,我们插入了填充。