簡體   English   中英

是什么導致我的數組地址在傳遞給函數時被破壞(更改)?

[英]What causes my array address to be corrupted (change) when passed to function?

我正在執行壓縮稀疏原始矩陣向量乘法(CSR SPMV):這涉及將數組A分成多個,然后通過引用函數傳遞這個塊,但是只有數組的第一部分( A[0]第一個塊開始數組的開頭)被修改。 然而,從第二個循環A[0 + chunkIndex] 開始,當函數讀取子數組時,它會跳轉並讀取超出總數組地址范圍的不同地址,盡管索引是正確的。

以供參考:

在此處輸入圖片說明


SPMV內核是:

void serial_matvec(size_t TS,  double *A, int *JA, int *IA,  double *X, double *Y)
{
    double sum;
    for (int i = 0; i < TS; ++i)
    {   
        sum = 0.0;
        for (int j = IA[i]; j < IA[i + 1]; ++j)
        {
                sum += A[j] * X[JA[j]]; // the error is here , the function reads diffrent 
                                        // address of A,  and JA, so the access 
                                       // will be out-of-bound
            }
            Y[i] = sum;
        }
    }

它被稱為這樣:

int chunkIndex = 0;
for(size_t k = 0; k < rows/TS; ++k)
{
    chunkIndex = IA[k * TS];
    serial_matvec(TS, &A[chunkIndex], &JA[chunkIndex], &IA[k*TS], &X[0], &Y[k*TS]);
}

假設我處理(8x8) Matrix ,並且每個塊處理2 行,因此循環k將是Rows /TS = 4 loops ,傳遞給函數的chunkIndex和數組將如下所示:

chunkIndex: 0 --> 循環 k = 0, &A[0], &JA[0]

chunkIndex: --> loop k = 1, &A[16], &JA[16] //[此處出錯,函數讀取不同地址]

chunkIndex: --> loop k = 2, &A[32], &JA[32] //[此處出錯,函數讀取不同地址]

chunkIndex: --> loop k = 3, &A[48], &JA[48] //[此處出錯,函數讀取不同地址]

當我運行代碼時,只有第一個塊正確執行,其他 3 個塊內存已損壞,數組指針跳入超出數組大小的邊界。

我已經手動檢查了所有參數的所有索引,它們都是正確的,但是當我打印地址時,它們不一樣。 (現在調試這個 3 天)

我使用了valgrind ,它報告了:

大小 8 的無效讀取使用大小 8的未初始化值總和 += A[j] * X[JA[j]];

我用-g -fsanitize=address編譯它,我得到了

堆緩沖區溢出

我試圖在函數之外手動訪問這些塊,它們是正確的,那么什么會導致堆內存像這樣損壞呢?

代碼在這里,這是我能做的最低限度。

問題是我在索引傳遞給函數的數組部分chunk時使用了全局索引(main 內的索引 ,因此出現了越界問題。

解決方案是在每次函數調用時從0開始索引子數組,但我遇到了另一個問題。 在每次函數調用時,我處理TS行,每一行都有不同數量的非零。

舉個例子,看圖片, chunk 1 ,抱歉我的筆跡不好,這樣更容易。 如您所見,我們將需要3 indices ,一個用於每個塊i處理的TS行,另一個是因為每行具有不同數量的非零j ,第三個用於索引傳遞的子數組l ,這是原來的問題。 在此處輸入圖片說明

並且serial_matvec函數將如下所示:

void serial_matvec(size_t TS, const double *A, const int *JA, const int *IA,
                   const double *X, double *Y) {
  int  l = 0;
  for (int i = 0; i < TS; ++i) {
    for (int j = 0; j < (IA[i + 1] - IA[i]); ++j) {
      Y[i] += A[l] * X[JA[l]];
      l++;
    }    
  }
}

帶有測試的完整代碼在這里如果有人有更優雅的解決方案,我們非常歡迎您。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM