gpt4 book ai didi

c - 是什么导致我的数组地址在传递给函数时被损坏(更改)?

转载 作者:行者123 更新时间:2023-11-30 16:09:04 25 4
gpt4 key购买 nike

我正在执行压缩稀疏原始矩阵 vector 乘法(CSR SPMV):这涉及将数组A划分为多个 block ,然后通过引用函数传递该 block ,但是只有数组的第一部分(A[0] 从数组开头开始的第一个 block )被修改。然而,从第二个循环A[0 + chunkIndex]开始,当函数读取子数组时,它会跳转并读取超出总数组地址范围的不同地址,尽管索引是正确的。

供引用:

enter image description here

<小时/>

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)矩阵,并且我处理每个 block 2行,因此循环k将为r ows/TS = 4 次循环,传递给函数的 chunkIndex 和数组如下:

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

chunkIndex: --> loop k = 1, &A[16], &JA[16] //[ERROR here, function reads different address]

chunkIndex: --> loop k = 2, &A[32], &JA[32] //[ERROR here, function reads different address]

chunkIndex: --> loop k = 3, &A[48], &JA[48] //[ERROR here, function reads different address]

当我运行代码时,只有第一个 block 正确执行,其他 3 个 block 内存已损坏,并且数组指针跳入超出数组大小的边界。

我已经手动检查了所有参数的所有索引,它们都是正确的,但是当我打印地址时它们并不相同。 (已经调试了3天了)

我使用了valgrind,它报告:

Invalid read of size 8 and Use of uninitialised value of size 8 at the sum += A[j] * X[JA[j]]; line

我用-g -fsanitize=address编译它,我得到了

heap-buffer-overflow

我尝试在函数之外手动访问这些 block ,它们是正确的,那么什么会导致堆内存像这样被损坏?

代码是here ,这是我起码能做到的。

最佳答案

问题是我在索引传递给函数的数组部分 (chunk) 时使用了全局索引(main 内的索引),因此输出 -越界问题。

解决方案是在每次函数调用时从 0 开始索引子数组,但我遇到了另一个问题。在每次函数调用时,我都会处理 TS 行,每行都有不同数量的非零。

举个例子,看图,chunk 1,抱歉我的笔迹不好,这样比较容易。正如您所看到的,我们需要 3 个索引,其中一个索引用于每个 block TSi ,另一个是因为每行有不同数量的非零 j ,第三个用于索引子数组传递了 l,这是最初的问题。 enter image description here

并且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++;
}
}
}

经过测试的完整代码是here如果有人有更优雅的解决方案,我们非常欢迎。

关于c - 是什么导致我的数组地址在传递给函数时被损坏(更改)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59216438/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com