Подтвердить что ты не робот

Являются ли valgrind "неинициализированным значением" предупреждения ложными срабатываниями в многопоточных процедурах BLAS ATLAS?

Я использую ATLAS для LAPACK и многопоточных процедур BLAS и заметил, что когда мои матрицы становятся достаточно большими, чтобы ATLAS использовал многопоточные версии BLAS, я получаю ошибки инициализации от Valgrind. Вот минимальный пример из моего кода:

#include <stdio.h>
#include <stdlib.h>

extern void dgetrf_(int *, int *, double *, int *, int *, int *);
extern void dgetri_(int *, double *, int *, int *, double *, int *, int *);
extern void dgemm_(char *, char *, int *, int *, int *, double *, double *, int *, double *, int *, double *, double *, int *);

int main(void)
{
    double *m1,*m2,*work,*temp;
    int dim = 576;
    int i,j,info;
    int lwork = dim * dim;
    int *ipiv;
    char transA = 'N';
    char transB = 'N';
    double alpha = 1.0;
    double beta = 0.0;

    m1 = malloc(dim*dim*sizeof(double));
    m2 = malloc(dim*dim*sizeof(double));
    temp = malloc(dim*dim*sizeof(double));
    ipiv = malloc(dim*sizeof(int));
    work = malloc(lwork*sizeof(double));

    for(i=0; i<dim; i++)
     {
       for(j=0; j<dim; j++)
        {
          if(i==j)
           {
             m1[i+dim*j] = .25;
             m2[i+dim*j] = .5;
           }
          else
           {
             m1[i+dim*j] = 0.0;
             m2[i+dim*j] = 0.0;
           }
        }
    }

    dgetrf_(&dim, &dim, m1, &dim, ipiv, &info);
    dgetri_(&dim, m1, &dim, ipiv, work, &lwork, &info);

    dgemm_(&transA, &transB, &dim, &dim, &dim, &alpha, m1, &dim, m2, &dim, &beta, temp, &dim);
    for(i=0; i<dim*dim; i++)
        m1[i] = temp[i];

    dgetrf_(&dim, &dim, m1, &dim, ipiv, &info);
    dgetri_(&dim, m1, &dim, ipiv, work, &lwork, &info);

    free(m1);
    free(m2);
    free(ipiv);
    free(work);
    free(temp);

    return 0;
}

(Примечание. Я проверил, чтобы убедиться, что матрицы не сингулярны, а они нет.)

Я скомпилирую программу:

gcc -Wall -DATLAS -m64 -g -c fermi.c
gcc -o fermi fermi.o -L/usr/lib64/atlas/ -lm -ltatlas

И запустите valgrind:

valgrind --leak-check=yes ./fermi

Когда я это делаю, я получаю 193 ошибки из 11 контекстов "Условный переход или перемещение зависит от неинициализированного значения (значений)", когда встречаются два экземпляра dgetrf_ и dgetri_.

==24999== Memcheck, a memory error detector
==24999== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==24999== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==24999== Command: ./fermi
==24999== 
==24999== Conditional jump or move depends on uninitialised value(s)
==24999==    at 0x524C62B: ??? (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x51C29E3: ATL_dgetf2 (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x51CD2BF: ATL_dtgetrfC (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x51CD2BF: ATL_dtgetrfC (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x51CD2BF: ATL_dtgetrfC (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x51CD2BF: ATL_dtgetrfC (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x520F538: atl_f77wrap_dgetrf_ (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x5210416: dgetrf_ (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x400A97: main (fermi.c:52)
==24999== 
==24999== Conditional jump or move depends on uninitialised value(s)
==24999==    at 0x524C66A: ??? (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x51C29E3: ATL_dgetf2 (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x51CD2BF: ATL_dtgetrfC (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x51CD2BF: ATL_dtgetrfC (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x51CD2BF: ATL_dtgetrfC (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x51CD2BF: ATL_dtgetrfC (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x520F538: atl_f77wrap_dgetrf_ (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x5210416: dgetrf_ (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x400A97: main (fermi.c:52)
==24999== 
==24999== Conditional jump or move depends on uninitialised value(s)
==24999==    at 0x524C6BE: ??? (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x51C29E3: ATL_dgetf2 (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x51CD2BF: ATL_dtgetrfC (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x51CD2BF: ATL_dtgetrfC (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x51CD2BF: ATL_dtgetrfC (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x51CD2BF: ATL_dtgetrfC (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x520F538: atl_f77wrap_dgetrf_ (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x5210416: dgetrf_ (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x400A97: main (fermi.c:52)
==24999== 
==24999== Conditional jump or move depends on uninitialised value(s)
==24999==    at 0x51C2A0B: ATL_dgetf2 (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x51CD2BF: ATL_dtgetrfC (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x51CD2BF: ATL_dtgetrfC (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x51CD2BF: ATL_dtgetrfC (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x51CD2BF: ATL_dtgetrfC (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x520F538: atl_f77wrap_dgetrf_ (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x5210416: dgetrf_ (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x400A97: main (fermi.c:52)
==24999== 
==24999== Conditional jump or move depends on uninitialised value(s)
==24999==    at 0x51C2A0D: ATL_dgetf2 (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x51CD2BF: ATL_dtgetrfC (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x51CD2BF: ATL_dtgetrfC (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x51CD2BF: ATL_dtgetrfC (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x51CD2BF: ATL_dtgetrfC (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x520F538: atl_f77wrap_dgetrf_ (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x5210416: dgetrf_ (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x400A97: main (fermi.c:52)
==24999== 
==24999== Conditional jump or move depends on uninitialised value(s)
==24999==    at 0x51C2A4E: ATL_dgetf2 (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x51CD2BF: ATL_dtgetrfC (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x51CD2BF: ATL_dtgetrfC (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x51CD2BF: ATL_dtgetrfC (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x51CD2BF: ATL_dtgetrfC (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x520F538: atl_f77wrap_dgetrf_ (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x5210416: dgetrf_ (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x400A97: main (fermi.c:52)
==24999== 
==24999== Conditional jump or move depends on uninitialised value(s)
==24999==    at 0x51C2A61: ATL_dgetf2 (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x51CD2BF: ATL_dtgetrfC (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x51CD2BF: ATL_dtgetrfC (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x51CD2BF: ATL_dtgetrfC (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x51CD2BF: ATL_dtgetrfC (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x520F538: atl_f77wrap_dgetrf_ (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x5210416: dgetrf_ (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x400A97: main (fermi.c:52)
==24999== 
==24999== Conditional jump or move depends on uninitialised value(s)
==24999==    at 0x524C2D7: ATL_daxpy (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x53426BB: ATL_dgerk_axpy (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x51C2AC7: ATL_dgetf2 (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x51CD2BF: ATL_dtgetrfC (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x51CD2BF: ATL_dtgetrfC (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x51CD2BF: ATL_dtgetrfC (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x51CD2BF: ATL_dtgetrfC (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x520F538: atl_f77wrap_dgetrf_ (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x5210416: dgetrf_ (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x400A97: main (fermi.c:52)
==24999== 
==24999== Conditional jump or move depends on uninitialised value(s)
==24999==    at 0x524C751: ??? (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x51C29E3: ATL_dgetf2 (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x51CD2BF: ATL_dtgetrfC (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x51CD2BF: ATL_dtgetrfC (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x51CD2BF: ATL_dtgetrfC (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x51CD2BF: ATL_dtgetrfC (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x520F538: atl_f77wrap_dgetrf_ (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x5210416: dgetrf_ (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x400A97: main (fermi.c:52)
==24999== 
==24999== Conditional jump or move depends on uninitialised value(s)
==24999==    at 0x51CD8E5: ATL_dtrtri (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x51C2EC3: ATL_dgetriC (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x520EFA5: atl_f77wrap_dgetri_ (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x520F684: dgetri_ (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x400AC0: main (fermi.c:53)
==24999== 
==24999== Conditional jump or move depends on uninitialised value(s)
==24999==    at 0x51CD8E7: ATL_dtrtri (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x51C2EC3: ATL_dgetriC (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x520EFA5: atl_f77wrap_dgetri_ (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x520F684: dgetri_ (in /usr/lib64/atlas/libtatlas.so.3.10)
==24999==    by 0x400AC0: main (fermi.c:53)
==24999== 
==24999== 
==24999== HEAP SUMMARY:
==24999==     in use at exit: 0 bytes in 0 blocks
==24999==   total heap usage: 2,024 allocs, 2,024 frees, 54,831,424 bytes allocated
==24999== 
==24999== All heap blocks were freed -- no leaks are possible
==24999== 
==24999== For counts of detected and suppressed errors, rerun with: -v
==24999== Use --track-origins=yes to see where uninitialised values come from
==24999== ERROR SUMMARY: 193 errors from 11 contexts (suppressed: 0 from 0)

Я нашел несколько ссылок, которые предполагают, что это может быть ложным положительным результатом того, как библиотека делает что-то, хотя они не очень сильно связаны с моим контекстом.

утечка памяти в dgemm_

https://www.open-mpi.org/community/lists/users/2007/05/3192.php

Итак, мой вопрос: является valgrind, дающий ложные положительные ошибки?

4b9b3361

Ответ 1

является valgrind, дающий ложные положительные ошибки?

Похоже, нет.

Вместо запуска valgrind с --leak-check=yes вы должны запустить его с помощью --track-origins=yes, чтобы узнать, откуда взялись неинициализированные значения, как было предложено valgrind в конце вывода. Вот что у меня с --track-origins=yes:

[ ~]$ valgrind --track-origins=yes ./a.out 
==17533== Memcheck, a memory error detector
==17533== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==17533== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==17533== Command: ./a.out
==17533== 
==17533== Conditional jump or move depends on uninitialised value(s)
==17533==    at 0x4F4362B: ??? (in /usr/lib64/atlas/libtatlas.so.3.10)
==17533==    by 0x4EB99E3: ATL_dgetf2 (in /usr/lib64/atlas/libtatlas.so.3.10)
==17533==    by 0x4EC42BF: ATL_dtgetrfC (in /usr/lib64/atlas/libtatlas.so.3.10)
==17533==    by 0x4EC42BF: ATL_dtgetrfC (in /usr/lib64/atlas/libtatlas.so.3.10)
==17533==    by 0x4EC42BF: ATL_dtgetrfC (in /usr/lib64/atlas/libtatlas.so.3.10)
==17533==    by 0x4EC42BF: ATL_dtgetrfC (in /usr/lib64/atlas/libtatlas.so.3.10)
==17533==    by 0x4F06538: atl_f77wrap_dgetrf_ (in /usr/lib64/atlas/libtatlas.so.3.10)
==17533==    by 0x4F07416: dgetrf_ (in /usr/lib64/atlas/libtatlas.so.3.10)
==17533==    by 0x400A29: main (fermi.c:50)
==17533==  Uninitialised value was created by a heap allocation
==17533==    at 0x4C2DB9D: malloc (vg_replace_malloc.c:299)
==17533==    by 0x40080B: main (fermi.c:22)

Таким образом, источником неинициализированных значений является эта строка кода:

temp = malloc(dim*dim*sizeof(double));

Затем он используется для инициализации m1, который передается в dgetrf_() в строке 50.

Я не знаком с библиотекой ATLAS, но я думаю, вам нужно как-то инициализировать переменную temp. Например, инициализация нуля temp с помощью calloc устраняет все эти ошибки valgrind:

temp = calloc(dim*dim,sizeof(double));