打印转置矩阵时出现的问题

Problems while printing out transposed matrix

提问人:szyjas 提问时间:11/14/2023 更新时间:11/14/2023 访问量:65

问:

我的问题是,在转置后打印出矩阵的第一行后,我收到一个错误,告诉我我试图访问无法访问的位置

第一篇文章与 asm 讨论,如果我没有告诉可能需要的东西文本 我在 C++ 中调用了一个用 asm 编写的转置函数

#include <iostream>
#include <windows.h>

extern "C" void transpose(INT64**, INT64);

// Function for displaying the matrix
void printMatrix(INT64** matrix, INT64 n) {
    for (INT64 i = 0; i < n; ++i) {
        for (INT64 j = 0; j < n; ++j) {
            std::cout << matrix[i][j] << " ";
        }
        std::cout << std::endl;
    }
}

int main() {
    INT64 n = 8; // Matrix size

    // Initialization of matrix A
    INT64** A = new INT64 * [n];
    for (INT64 i = 0; i < n; ++i) {
        A[i] = new INT64[n];
        for (INT64 j = 0; j < n; ++j) {
            A[i][j] = i * n + j; // Filling matrix A
        }
    }

    std::cout << "Matrix before transposition:" << std::endl;
    printMatrix(A, n); // Display the matrix before transposition

    // Calling the transpose function
    transpose(A, n);

    std::cout << "Matrix after transposition:" << std::endl;
    printMatrix(A, n); // Display the matrix after transposition

    // Deallocate memory
    for (INT64 i = 0; i < n; ++i) {
        delete[] A[i];
    }
    delete[] A;

    return 0;
}

这是我的代码最后一次迭代中使用的 asm 函数

; TransposeSquareMatrix(A, n)
    mov     rdi, rcx
    mov     rsi, rdx
    mov     rbx, rdi        ; Address A is in RDI
    mov     rcx, rsi        ; Dimension n is in RSI
    imul    r8, rsi, 8      ; Step between rows
    dec     rcx
    jz      .c              ; It's a (1 x 1) matrix
.a: push    rcx             ; (1)
    mov     rsi, rbx        ; Column address
    mov     rdi, rbx        ; Row address
.b: add     rsi, 8          ; To next element in this row
    add     rdi, r8         ; To next element in this column
    mov     rax, [rsi]      ; Swap 2 elements
    mov     rdx, [rdi]
    mov     [rdi], rax
    mov     [rsi], rdx
    dec     rcx
    jnz     .b
    lea     rbx, [rbx + r8 + 8] ; To next element on main diagonal
    pop     rcx             ; (1)
    dec     rcx
    jnz     .a              ; Continu until (1 x 1) matrix
.c: ret

有什么问题?是 c++ 代码还是其他东西?

C++ 程序集 转置

评论

1赞 Jester 11/14/2023
您没有保留调用约定 (和 ) 所需的寄存器。也许选择其他不需要保留的寄存器。rbxrsirdi
1赞 Peter Cordes 11/14/2023
INT64**不是像 那样的连续 2D 数组,而是指向数组的指针数组。请参阅如何使用 new 在 C++ 中声明 2d 数组?。使用额外的间接级别,访问元素需要 2 次加载;这就是为什么这样做效率低下的原因。我认为您的 asm 将其视为适当的 2D 数组。int64_t arr[n][m]
1赞 PaulMcKenzie 11/14/2023
还有 How-to-create-a-contiguous-2d-array-in-c++。即使你没有使用汇编程序,这也是创建具有统一行数和列数的矩阵的绝对糟糕的方法。如果有 10000 行怎么办?内存碎片遍布屋顶,可能在中间某处的创建循环中失败,等等。// Initialization of matrix Anew[]
0赞 Peter Cordes 11/14/2023
@PaulMcKenzie:我不建议这样做。连续分配,但指针数组仍然有额外的间接级别来访问它,从而阻止了某些编译器优化。例如,code-gen 不能假设 是 不同的元素,因为它不能假设指针数组的 2 个条目是不同的。与实际的二维数组相比,可以对两个矩阵进行循环之外的单个重叠检查,例如回退到非矢量化循环。或者编写一个类,将 2D 索引重载到一个平面中,或者A[x][y]A[z][y][]int[]std::vector<int>
1赞 Thomas Matthews 11/14/2023
我建议将单个指针传递到连续内存。要访问矩阵槽,请使用公式 这可能比传递 2d 矩阵更快。INT64 value = arr[(row * column_size) + column];

答: 暂无答案