Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are valgrind "uninitialized value" warnings false positives in ATLAS multithreaded BLAS routines?

I am using ATLAS for LAPACK and multithreaded BLAS routines, and have noticed that when my matrices get large enough for ATLAS to use the multithreaded versions of BLAS, I get initialization errors from Valgrind. Here is a minimal example from my code:

#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;
}

(Note: I've checked to make sure the matrices aren't singular and they aren't.)

I compile the program:

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

And run valgrind:

valgrind --leak-check=yes ./fermi

When I do this I get 193 errors from 11 contexts of "Conditional jump or move depends on uninitialised value(s)" when the second instances of dgetrf_ and dgetri_ are encountered.

==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)

I have found some links that suggest this could be a false positive coming from the way the library is doing things, though they aren't related very much to my context.

memory leak in dgemm_

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

So my question: is valgrind giving me false positive errors?

like image 974
Emilie Avatar asked Apr 25 '17 19:04

Emilie


People also ask

Can Valgrind be wrong?

Yes, there are false positives with Valgrind, that's why it has suppression files for particular glibc and gcc versions, for example. The false positives may arise if you are using older valgrind with newer gcc and glibc, i.e., valgrind 3.3 with glibc 2.9.

What does conditional jump mean in Valgrind?

Uninitialized value errors The error message "Conditional jump or move depends on uninitialized value(s)" essentially means Valgrind has determined that the result of your program depends on uninitialized memory. Sometimes you will also see the message "Use of uninitialized value of size N".


1 Answers

is valgrind giving me false positive errors?

Looks like no.

Instead of running valgrind with --leak-check=yes you should have run it with --track-origins=yes to see where uninitialised values come from as suggested by valgrind at the end of the output. Here is what I've got with --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)

So the source of uninitialised values is this line of code:

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

It is then used to initialise m1 which is passed to dgetrf_() on line 50.

I'm not familiar with ATLAS library but I guess you should somehow initialise temp variable. For example zero initialising temp with calloc resolves all these valgrind errors:

temp = calloc(dim*dim,sizeof(double));
like image 115
ks1322 Avatar answered Oct 11 '22 20:10

ks1322