public
Created

Accelerate framework bug with fork

  • Download Gist
bug.c
C
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
/*
* This small snippet shows an issue when calling dgemm for square matrices above a certain size inside a forked child process.
*
* To reproduce the issue:
* - compile it ("gcc -framework Accelerate bug.c -o bug")
* - ./bug 64 (64x64 matrix) will show the output for d matrix for both parents and child:
computing for size 64
c[0][0] is 64.000000
parent d[0][0] is 64.000000
child d[0][0] is 64.000000
 
* - ./bug 65 (65x65 matrix) will not show the output for child process
computing for size 65
c[0][0] is 65.000000
parent d[0][0] is 65.000000
 
* sgemm does not have the issue, and not calling cblas_dgemm before fork does not either.
* We also attached the valgrind ouptut, which suggests an issue with Grand Central.
*/
 
#include <string.h>
#include <stdio.h>
#include <unistd.h>
 
#include <Accelerate/Accelerate.h>
 
void* xmalloc(size_t n)
{
void* tmp;
 
tmp = malloc(n);
if (tmp == NULL) {
fprintf(stderr, "You are about to die\n");
exit(EXIT_FAILURE);
} else {
return tmp;
}
}
 
int main(int argc, char *argv[])
{
int n, lda, ldb, ldc;
int i;
 
double *a, *b, *c, *d;
size_t n_bytes;
 
pid_t p;
 
if (argc != 2) {
fprintf(stderr, "USAGE: %s size\n", argv[0]);
exit(EXIT_FAILURE);
} else {
n = atoi(argv[1]);
printf("computing for size %d\n", n);
}
 
lda = n;
ldb = n;
ldc = n;
 
n_bytes = sizeof(*a) * n * n;
 
a = xmalloc(n_bytes);
b = xmalloc(n_bytes);
c = xmalloc(n_bytes);
d = xmalloc(n_bytes);
 
for(i = 0; i < n * n; ++i) {
a[i] = 1;
b[i] = 1;
}
 
/* If this call is disabled, the crash disappears */
#if 1
cblas_dgemm(CblasRowMajor,
CblasNoTrans, CblasNoTrans, n, n, n,
1.0, a, lda, b, ldb, 0.0, c, ldc);
printf("c[0][0] is %f\n", c[0]);
#endif
 
p = fork();
if (p == 0) {
cblas_dgemm(CblasRowMajor,
CblasNoTrans, CblasNoTrans, n, n, n,
1.0, a, lda, b, ldb, 0.0, d, ldc);
printf("child d[0][0] is %f\n", d[0]);
} else {
cblas_dgemm(CblasRowMajor,
CblasNoTrans, CblasNoTrans, n, n, n,
1.0, a, lda, b, ldb, 0.0, d, ldc);
printf("parent d[0][0] is %f\n", d[0]);
}
 
return 0;
}
gistfile1.txt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
==39502== Memcheck, a memory error detector
==39502== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==39502== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==39502== Command: ./a.out 65
==39502==
--39502-- ./a.out:
--39502-- dSYM directory is missing; consider using --dsymutil=yes
computing for size 65
c[0][0] is 65.000000
UNKNOWN task message [id 3403, to mach_task_self(), reply 0x2e03]
parent d[0][0] is 65.000000
==39502==
==39502== HEAP SUMMARY:
==39502== in use at exit: 143,723 bytes in 43 blocks
==39502== total heap usage: 65 allocs, 22 frees, 1,459,867 bytes allocated
==39502==
==39503==
==39503== Process terminating with default action of signal 10 (SIGBUS)
==39503== Non-existent physical address at address 0x108
==39503== at 0x373324: dispatch_group_async_f (in /usr/lib/system/libdispatch.dylib)
==39503== by 0xFD565F: dgemmGCD (in /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib)
==39503== by 0xB62A47: cblas_dgemm (in /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib)
==39503== by 0x100000CF9: main (in ./a.out)
==39503==
==39503== HEAP SUMMARY:
==39503== in use at exit: 146,067 bytes in 47 blocks
==39503== total heap usage: 58 allocs, 11 frees, 804,139 bytes allocated
==39503==
==39502== LEAK SUMMARY:
==39502== definitely lost: 101,440 bytes in 5 blocks
==39502== indirectly lost: 0 bytes in 0 blocks
==39502== possibly lost: 33,800 bytes in 1 blocks
==39502== still reachable: 8,483 bytes in 37 blocks
==39502== suppressed: 0 bytes in 0 blocks
==39502== Rerun with --leak-check=full to see details of leaked memory
==39502==
==39502== For counts of detected and suppressed errors, rerun with: -v
==39502== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 1 from 1)
==39503== LEAK SUMMARY:
==39503== definitely lost: 40 bytes in 2 blocks
==39503== indirectly lost: 0 bytes in 0 blocks
==39503== possibly lost: 0 bytes in 0 blocks
==39503== still reachable: 146,027 bytes in 45 blocks
==39503== suppressed: 0 bytes in 0 blocks
==39503== Rerun with --leak-check=full to see details of leaked memory
==39503==
==39503== For counts of detected and suppressed errors, rerun with: -v
==39503== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 1 from 1)

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.