我正在尝试将MKL稀疏BLAS用于行/列数为100M的CSR矩阵。当我将其增加到100M时,我的源代码似乎可以很好地处理10M行/列,但却出现了segfault。
我将问题隔离到以下代码片段:
void TestSegfault1() {
float values[1] = { 1.0f };
int col_indx[1] = { 0 };
int rows_start[1] = { 0 };
int rows_end[1] = { 1 };
// Step 1. Create 1 x 100M matrix
// with single non-zero value at (0,0)
sparse_matrix_t A;
mkl_sparse_s_create_csr(
&A, SPARSE_INDEX_BASE_ZERO, 1, 100000000,
rows_start, rows_end, col_indx, values);
// Step 2. Transpose it to get 100M x 1 matrix
sparse_matrix_t B;
mkl_sparse_convert_csr(A, SPARSE_OPERATION_TRANSPOSE, &B);
}
此函数在带有回溯的mkl_spare_convert_csr中分段故障
#0 0x00000000004c0d03 in mkl_sparse_s_convert_csr_i4_avx ()
#1 0x0000000000434061 in TestSegfault1 ()
对于略有不同(但基本相同)的代码,它有一个更详细的信息:
#0 0x00000000008fc09b in mkl_serv_free ()
#1 0x000000000099949e in mkl_sparse_s_export_csr_data_i4_avx ()
#2 0x0000000000999ee4 in mkl_sparse_s_convert_csr_i4_avx ()
显然内存分配出了问题。它看起来确实像是某种从外部溢出的整数。MKL的构建使用了MKL_INT=INT=int32。
确实是这样吗?稀疏BLAS CSR矩阵中我可以具有的行数限制是<100M(看起来更像~65M)?还是我做错了?
第1版:MKL版本字符串为"英特尔(R)数学内核库11.3.1版产品内部版本20151021,适用于英特尔(R)64体系结构应用程序"。
编辑2:想明白了。在为内部每线程缓冲区分配内存时,确实存在一种微妙的整数溢出。在mkl_sparse_s_export_csr_data_i4_avx内部的某个时刻,它尝试分配(omp_get_max_threads()+1)*num_rows*4字节;该数字不适合32位有符号整数。对mkl_serv_malloc的后续调用会导致内存损坏,并最终导致segfault。一种可能的解决方案是通过omp_set_num_threads调用来更改OpenMP线程的数量。
你能检查一下MKL上一个版本的例子吗?我在MKL 11.3.2上运行它,它正确地通过了100M矩阵。然而,这可能取决于您机器上的线程数(矩阵大小乘以线程数必须小于max-int)。为了防止出现这种问题,我强烈建议使用ilp64版本的MKL库谢谢Alex
查看此示例如何与最新的mkl 2019 u4配合使用。使用ILP64模式编译示例,如下所示:
icc -I/opt/intel/compilers_and_libraries_2019/linux/mkl/include test_csr.cpp
-L/opt/intel/compilers_and_libraries_2019/linux/mkl/lib/intel64 -lmkl_core -lmkl_intel_ilp64 -lmkl_intel_thread -liomp5 -lpthread -lm -ldl
/a.outmkl_spare_convert_csr通过