我尝试使用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转置是否会比仅循环每个索引更慢......
答案 0 :(得分:1)
你实际上不需要垫,是吗?您只是建议使用您已经拥有的4x4 SSE转置例程,对吧?
矩阵转置不会移动对角线元素(包括第一个和最后一个)。 3x3转置具有更少的数据移动:仅需要加载/存储7个元素。
1 2 3 1 4 7
4 5 6 => 2 5 8
7 8 9 3 6 9
如果您的元素是4B(int
或float
,而不是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
您在上面的输出中看到填充矩阵较大,我们插入了填充。