Προς το περιεχόμενο

Προτεινόμενες αναρτήσεις

Δημοσ.

Καλημέρα σας,

 

έχω γράψει ένα κώδικα που υπολογίζει γινόμενο πίνακα-διανύσματος

για αραιούς πίνακες σε μορφή αποθήκευσης COO. Τα έκανα όλα κα-

λά αλλά προφανώς δε μπορούσα να σταθώ σε χλωρό κλαρί, οπότε

έβαλα με το νου μου να κάνω τον κώδικα να φαίνεται πιο επίσημος.

Κάθησα έτσι και άρχιζα να εφαρμόζω πραγματάκια που έμαθα από το

βιβλίο Interfaces & Implementations για να του δώσω άλλο αέρα. Όλα

τα έβαλα καλά, αλλά έχω κολλήσει στο garbage collection. Μου φαίνε-

ται περίεργο το πρόβλημα, μπορεί να φταίει και η ώρα.

 

To Interface και το Implementation είναι τα εξής:

coo_sparse.h

 

 

#ifndef COO_SPARSE_H_7EUNGWRE
#define COO_SPARSE_H_7EUNGWRE
#include <stdlib.h> // for size_t

#define T coo_triplet_T
typedef struct T *T;	/* T is a pointer to struct T */

#define COO_LENGTH(A)       (A->nz)
#define COO_GET_VALUE(A, i) (A->val[i])
#define COO_GET_COL_I(A, i) (A->col_ind[i])
#define COO_GET_ROW_I(A, i) (A->row_ind[i])


/** ===========================================================================
 * Creates a matrix in a triplet form according to COO scheme.
 * @param nz Number of non-zero elements
 * @return Pointer to the triplet form
 */
extern T coo_new_triplet(size_t nz);


/** ===========================================================================
 * Initialize the value array of the triplet.
 * @param A Sparse matrix in triplet COO scheme
 * @param val Pointer to the value array
 */
extern void coo_init_value(T A, double *val);


/** ===========================================================================
 * Initialize the column index array of the triplet.
 * @param A Sparse matrix in triplet COO scheme
 * @param val Pointer to the column index array
 */
extern void coo_init_col_ind(T A, size_t *col);


/** ===========================================================================
 * Initialize the row index array of the triplet.
 * @param A Sparse matrix in triplet COO scheme
 * @param val Pointer to the row index array
 */
extern void coo_init_row_ind(T A, size_t *row);


/** ===========================================================================
 * Delete the given sparse matrix which uses the COO scheme.
 * @param A Sparse matrix in triplet COO scheme
 */
extern void coo_delete_triplet(T A);


/** ===========================================================================
 * Multiplies matrix A by vector x and stores the result in vector y.
 * @param A Input matrix
 * @param x Input vactor
 * @param y Result of A*x
 */
extern void coo_sparse_matrix_vector_mul(const T A,
                                         const double *x,
                                         double *y);

#undef T
#endif /* COO_SPARSE_H_7EUNGWRE */
 

 

 

 

coo_sparse.c

 

 

#include "coo_sparse.h"
#include <assert.h>
#include <stdio.h>
#include <string.h>

#define T coo_triplet_T

/**
 * COO triplet data type
 */
struct T {
    double *val;
    size_t *col_ind;
    size_t *row_ind;
    size_t nz;
};


T coo_new_triplet(size_t nz)
{
    T ret = malloc(sizeof(T));

    register size_t bytes = nz * sizeof(size_t);
    ret->val = malloc(nz * sizeof(double));
    ret->col_ind = malloc(bytes);
    ret->row_ind = malloc(bytes);
    ret->nz = nz;

    if (!ret || !ret->val || !ret->col_ind || !ret->row_ind) {
        perror("coo_serial");
        exit(EXIT_FAILURE);
    }

    return ret;
}


void coo_init_value(T A, double *val)
{
    assert(A);
    assert(val);

    memcpy(A->val, val, A->nz * sizeof(double));
}


void coo_init_col_ind(T A, size_t *col)
{
    assert(A);
    assert(col);

    memcpy(A->col_ind, col, A->nz * sizeof(size_t));
}


void coo_init_row_ind(T A, size_t *row)
{
    assert(A);
    assert(row);

    memcpy(A->row_ind, row, A->nz * sizeof(size_t));
}


void coo_delete_triplet(T A)
{
    assert(A);

    free(A->val);     A->val     = NULL;
    free(A->col_ind); A->col_ind = NULL;
    free(A->row_ind); A->row_ind = NULL;
    free(A);          A          = NULL;
}


void coo_sparse_matrix_vector_mul(const T A,
                                  const double *x,
                                  double *y)
{
    assert(A);

    for (size_t i = 0; i < COO_LENGTH(A); i++) {
        y[COO_GET_ROW_I(A, i)] += COO_GET_VALUE(A, i) * x[COO_GET_COL_I(A, i)];
    }
}

#undef T
 

 

 

 

Τα παραπάνω τα χρησιμοποιώ εδώ:

 

 

#include "test_suite.h"
#include "coo_sparse.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

void test_suite(void)
{
    /* TEST 1 */
    {
        size_t size = 3;
        size_t nz = 3;
        coo_triplet_T test = coo_new_triplet(nz);

        double val[3]     = {1., 2., 3.};
        size_t col_ind[3] = {0,  2,  2};
        size_t row_ind[3] = {0,  0,  2};
        coo_init_value(test, val);
        coo_init_col_ind(test, col_ind);
        coo_init_row_ind(test, row_ind);

        double x[3]     = {10., 20., 30.};
        double y_sol[3] = {70., 0.,  90.};

        double y_res[3] = {0.};

        coo_sparse_matrix_vector_mul(test, x, y_res);

        if (!memcmp(y_res, y_sol, size * sizeof(double))) {
            puts("[TEST 1] *** SUCCESS ***");
        } else {
            puts("[TEST 1] !!! FAILURE !!!");
        }

        coo_delete_triplet(test);
    }

    /* TEST 2 */
    {
        size_t size = 8;
        size_t nz = 14;
        coo_triplet_T test = coo_new_triplet(nz);

        double val[14]     = {6., 9., 4., 4., 5., 3., 5., 8., 6., 5., 4., 3., 2., 2.};
        size_t col_ind[14] = {0,  2,  5,  5,  1,  2,  3,  4,  4,  5,  5,  6,  6,  7};
        size_t row_ind[14] = {0,  0,  0,  1,  2,  3,  3,  3,  4,  5,  6,  6,  7,  7};
        coo_init_value(test, val);
        coo_init_col_ind(test, col_ind);
        coo_init_row_ind(test, row_ind);

        double x[8]     = { 1., 3.,  6.,  2., 1., 0.,  5.,  3.};
        double y_sol[8] = {60., 0., 15., 36., 6., 0., 15., 16.};

        double y_res[8] = {0.};

        coo_sparse_matrix_vector_mul(test, x, y_res);

        if (!memcmp(y_res, y_sol, size * sizeof(double))) {
            puts("[TEST 2] *** SUCCESS ***");
        } else {
            puts("[TEST 2] !!! FAILURE !!!");
        }

        coo_delete_triplet(test);
    }
}
 

 

 

 

Εκεί που μου εμφανίζει πρόβλημα, σκάει δηλαδή στην εκτέλεση το πρόγραμμα είναι αυτά

που συμβαίνουν στην coo_delete_triplet:

 

 

 ✘ gon1332@localhost ⮀ ~/Dropbox/ΤΜΗΥΤΔ/5ο έτος/Θ - Παράλληλοι και Δικτυακοί Υπολογισμοί/Εργασίες/proj3/src ⮀ ./serial
[TEST 1] *** SUCCESS ***
*** glibc detected *** ./serial: munmap_chunk(): invalid pointer: 0x0000000000d6f030 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x76a16)[0x7fdec5859a16]
./serial[0x400a60]
./serial[0x400d45]
./serial[0x400fa4]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xfd)[0x7fdec5801ead]
./serial[0x400659]
======= Memory map: ========
00400000-00402000 r-xp 00000000 08:04 10894723                           /home/gon1332/Dropbox/ΤΜΗΥΤΔ/5ο έτος/Θ - Παράλληλοι και Δικτυακοί Υπολογισμοί/Εργασίες/proj3/src/serial
00601000-00602000 rw-p 00001000 08:04 10894723                           /home/gon1332/Dropbox/ΤΜΗΥΤΔ/5ο έτος/Θ - Παράλληλοι και Δικτυακοί Υπολογισμοί/Εργασίες/proj3/src/serial
00d6f000-00d90000 rw-p 00000000 00:00 0                                  [heap]
7fdec55cd000-7fdec55e2000 r-xp 00000000 08:04 394715                     /lib/x86_64-linux-gnu/libgcc_s.so.1
7fdec55e2000-7fdec57e2000 ---p 00015000 08:04 394715                     /lib/x86_64-linux-gnu/libgcc_s.so.1
7fdec57e2000-7fdec57e3000 rw-p 00015000 08:04 394715                     /lib/x86_64-linux-gnu/libgcc_s.so.1
7fdec57e3000-7fdec5965000 r-xp 00000000 08:04 393657                     /lib/x86_64-linux-gnu/libc-2.13.so
7fdec5965000-7fdec5b65000 ---p 00182000 08:04 393657                     /lib/x86_64-linux-gnu/libc-2.13.so
7fdec5b65000-7fdec5b69000 r--p 00182000 08:04 393657                     /lib/x86_64-linux-gnu/libc-2.13.so
7fdec5b69000-7fdec5b6a000 rw-p 00186000 08:04 393657                     /lib/x86_64-linux-gnu/libc-2.13.so
7fdec5b6a000-7fdec5b6f000 rw-p 00000000 00:00 0 
7fdec5b6f000-7fdec5b8f000 r-xp 00000000 08:04 393651                     /lib/x86_64-linux-gnu/ld-2.13.so
7fdec5d66000-7fdec5d69000 rw-p 00000000 00:00 0 
7fdec5d8b000-7fdec5d8e000 rw-p 00000000 00:00 0 
7fdec5d8e000-7fdec5d8f000 r--p 0001f000 08:04 393651                     /lib/x86_64-linux-gnu/ld-2.13.so
7fdec5d8f000-7fdec5d90000 rw-p 00020000 08:04 393651                     /lib/x86_64-linux-gnu/ld-2.13.so
7fdec5d90000-7fdec5d91000 rw-p 00000000 00:00 0 
7fffa146d000-7fffa148e000 rw-p 00000000 00:00 0                          [stack]
7fffa149b000-7fffa149d000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]
[1]    12235 abort      ./serial
 

 

 

 

Έτρεξα και τον gdb για να δω τί περνιέται σε κάθε stack frame και όλα μου φαίνονται φυσιολογικά.

Βέβαια αυτό που μου προκαλλεί τις δυσλειτουργίες μπορεί να κρύβεται αλλού όπως συχνά συμβαί-

νει με τη C.

 

gdb output:

 

 

(gdb) bt full
#0  0x00007ffff7a83165 in *__GI_raise (sig=<optimized out>) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64
        pid = <optimized out>
        selftid = <optimized out>
#1  0x00007ffff7a863e0 in *__GI_abort () at abort.c:92
        act = {__sigaction_handler = {sa_handler = 0x7fffffffd768, sa_sigaction = 0x7fffffffd768}, sa_mask = {__val = {140737488344912, 
              140737488349202, 156, 140737349550107, 3, 140737488344922, 6, 140737349550111, 2, 140737488344910, 2, 140737349541097, 1, 
              140737349550107, 3, 140737488344916}}, sa_flags = 12, sa_restorer = 0x7ffff7ba001f}
        sigs = {__val = {32, 0 <repeats 15 times>}}
#2  0x00007ffff7abe1cb in __libc_message (do_abort=<optimized out>, fmt=<optimized out>) at ../sysdeps/unix/sysv/linux/libc_fatal.c:189
        ap = {{gp_offset = 40, fp_offset = 48, overflow_arg_area = 0x7fffffffe0d0, reg_save_area = 0x7fffffffdfe0}}
        ap_copy = {{gp_offset = 16, fp_offset = 48, overflow_arg_area = 0x7fffffffe0d0, reg_save_area = 0x7fffffffdfe0}}
        fd = 3
        on_2 = <optimized out>
        list = <optimized out>
        nlist = 0
        cp = <optimized out>
        written = false
#3  0x00007ffff7ac7a16 in malloc_printerr (action=3, str=0x7ffff7ba2098 "munmap_chunk(): invalid pointer", ptr=<optimized out>) at malloc.c:6312
        buf = "0000000000602030"
        cp = 0x7ffff7b97d40 <_itoa_lower_digits> "0123456789abcdefghijklmnopqrstuvwxyz"
#4  0x0000000000400a60 in coo_delete_triplet (A=0x602010) at coo_sparse.c:69
No locals.
#5  0x0000000000400d45 in test_suite () at test_suite.c:35
        nz = 3
        test = 0x602010
        val = {1, 2, 3}
        size = 3
        col_ind = {0, 2, 2}
        row_ind = {0, 0, 2}
        x = {10, 20, 30}
        y_sol = {70, 0, 90}
        y_res = {70, 0, 90}
#6  0x0000000000400fa4 in main () at coo_serial.c:8
No locals. 

 

 

 

Όλα φαίνονται ok, και τα tests που έφτιαξα περνάνε αν βάλω σε σχόλια το garbage collection.

Τι μπορεί να φταίει;

 

ΣΗΜΕΙΩΣΗ: Ο κώδικας δουλεύει ως έχει και έχω έκδοση που δουλεύουν όλα ρολόι,

απλά θέλω να δοκιμάσω στην πράξη κάποια πράγματα για να μάθω από αυτά.

 

Έχω σε attachment όλο τον κώδικα μαζί με makefile. Ο κώδικας έχει δοκιμαστεί μόνο σε linux,

χωρίς όμως να περιέχει τίποτα το unix-οειδές.

src.zip

Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε

Πρέπει να είστε μέλος για να αφήσετε σχόλιο

Δημιουργία λογαριασμού

Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!

Δημιουργία νέου λογαριασμού

Σύνδεση

Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.

Συνδεθείτε τώρα
  • Δημιουργία νέου...