Issue with dot product: only calculating at second request to calculate

Issue #96 wontfix
Daniel Baker created an issue

I'm sorry for the trouble... I seem to be having trouble getting a matrix to update when being assigned to. I'm able to get it to update -- but only when I recalculate the original expression.

I'm using a test case of creating a matrix of dot products between all rows in a matrix. My test is 3 rows with two columns.

The following code snippet and output shows this strange behavior:

    blaze::SymmetricMatrix<MatrixType> &operator()(MatrixType &a, blaze::SymmetricMatrix<MatrixType> &ret) const {
        LOG_DEBUG("rows: %zu\n", a.rows());
        if(ret.rows() != a.rows()) ret.resize(a.rows());
        assert(ret.rows() == a.rows());
        assert(ret.columns() == a.rows());
        const size_t len(a.rows());
        for(size_t i(0); i < len; ++i) {
            for(size_t j = i; j < len; ++j) {
                ret(i, j) = static_cast<FloatType>(dot(row(a, i), row(a, j)));
                ret(i, j) += c_; 
                LOG_INFO("Cast, no storing of rows, addition: %zu, %zu value is %lf. \n", i, j, ret(i, j));
            }   
        }   
        for(size_t i(0); i < len; ++i) {
            for(size_t j = i; j < len; ++j) {
                LOG_INFO("Before second calculation: %zu, %zu value is %lf. \n", i, j, ret(i, j));
                //LOG_INFO("Cast, no temporary, but with recalculation: %zu, %zu value is %lf. Second calculation: %lf\n", i, j, ret(i, j), dot(row(a, i), row(a, j)) + c_);
            }   
        }   
        for(size_t i(0); i < len; ++i) {
            for(size_t j = i; j < len; ++j) {
                LOG_INFO("Before third calculation: %zu, %zu value is %lf. \n", i, j, ret(i, j));
                LOG_INFO("Cast, no temporary, but with recalculation: %zu, %zu value is %lf. Second calculation: %lf\n", i, j, ret(i, j), dot(row(a, i), row(a, j)) + c_);
            }   
        }   
        ret *= k_; 
        ret = tanh(ret);
        return ret;
    }   
[operator()] Cast, no storing of rows, addition: 0, 0 value is 0.000000. 
[operator()] Cast, no storing of rows, addition: 0, 1 value is 0.000000. 
[operator()] Cast, no storing of rows, addition: 0, 2 value is 0.000000. 
[operator()] Cast, no storing of rows, addition: 1, 1 value is 0.000000. 
[operator()] Cast, no storing of rows, addition: 1, 2 value is 0.000000. 
[operator()] Cast, no storing of rows, addition: 2, 2 value is 0.000000. 
[operator()] Before second calculation: 0, 0 value is 0.000000. 
[operator()] Before second calculation: 0, 1 value is 0.000000. 
[operator()] Before second calculation: 0, 2 value is 0.000000. 
[operator()] Before second calculation: 1, 1 value is 0.000000. 
[operator()] Before second calculation: 1, 2 value is 0.000000. 
[operator()] Before second calculation: 2, 2 value is 0.000000. 
[operator()] Before third calculation: 0, 0 value is 0.000000. 
[operator()] Cast, no temporary, but with recalculation: 0, 0 value is 1795203.675000. Second calculation: 0.000000
[operator()] Before third calculation: 0, 1 value is 1795203.675000. 
[operator()] Cast, no temporary, but with recalculation: 0, 1 value is 28351239.800000. Second calculation: 0.000000
[operator()] Before third calculation: 0, 2 value is 28351239.800000. 
[operator()] Cast, no temporary, but with recalculation: 0, 2 value is 737061.237500. Second calculation: 0.000000
[operator()] Before third calculation: 1, 1 value is 737061.237500. 
[operator()] Cast, no temporary, but with recalculation: 1, 1 value is 450901503.800000. Second calculation: 0.000000
[operator()] Before third calculation: 1, 2 value is 450901503.800000. 
[operator()] Cast, no temporary, but with recalculation: 1, 2 value is 5966527.800000. Second calculation: 0.000000
[operator()] Before third calculation: 2, 2 value is 5966527.800000. 
[operator()] Cast, no temporary, but with recalculation: 2, 2 value is 10499647.800000. Second calculation: 0.000000

Maybe there's something I'm failing to understand about expression templates, but this code is not updating the matrix when I tell it to.

Comments (4)

  1. Klaus Iglberger

    Hi dnbh!

    I tried to reproduce your problem by using both DynamicMatrix<float,rowMajor> and CompressedMatrix<float,rowMajor> for MatrixType, 2.0F for c_ and 3.0F for k_. Also, I use only a single thread and added a couple of additional output statements to show the matrix after each step. Finally, I used the following arbitrary 3x2 input matrix for a:

    ( 1.1F 2.2F )
    ( 3.3F 4.4F )
    ( 5.5F 6.6F )
    

    For both cases (dense and sparse MatrixType) the function produces the following output:

    rows: 3
    Cast, no storing of rows, addition: 0, 0 value is 8.05. 
    Cast, no storing of rows, addition: 0, 1 value is 15.31. 
    Cast, no storing of rows, addition: 0, 2 value is 22.57. 
    Cast, no storing of rows, addition: 1, 1 value is 32.25. 
    Cast, no storing of rows, addition: 1, 2 value is 49.19. 
    Cast, no storing of rows, addition: 2, 2 value is 75.81. 
     ret =
    (         8.05        15.31        22.57 )
    (        15.31        32.25        49.19 )
    (        22.57        49.19        75.81 )
    
    Before second calculation: 0, 0 value is 8.05. 
    Before second calculation: 0, 1 value is 15.31. 
    Before second calculation: 0, 2 value is 22.57. 
    Before second calculation: 1, 1 value is 32.25. 
    Before second calculation: 1, 2 value is 49.19. 
    Before second calculation: 2, 2 value is 75.81. 
     ret =
    (         8.05        15.31        22.57 )
    (        15.31        32.25        49.19 )
    (        22.57        49.19        75.81 )
    
    Before third calculation: 0, 0 value is 8.05. 
    Cast, no temporary, but with recalculation: 0, 0 value is 8.05. Second calculation: 8.05
    Before third calculation: 0, 1 value is 15.31. 
    Cast, no temporary, but with recalculation: 0, 1 value is 15.31. Second calculation: 15.31
    Before third calculation: 0, 2 value is 22.57. 
    Cast, no temporary, but with recalculation: 0, 2 value is 22.57. Second calculation: 22.57
    Before third calculation: 1, 1 value is 32.25. 
    Cast, no temporary, but with recalculation: 1, 1 value is 32.25. Second calculation: 32.25
    Before third calculation: 1, 2 value is 49.19. 
    Cast, no temporary, but with recalculation: 1, 2 value is 49.19. Second calculation: 49.19
    Before third calculation: 2, 2 value is 75.81. 
    Cast, no temporary, but with recalculation: 2, 2 value is 75.81. Second calculation: 75.81
     ret =
    (         8.05        15.31        22.57 )
    (        15.31        32.25        49.19 )
    (        22.57        49.19        75.81 )
    

    All three steps properly compute the dot products and update the matrix. Also, the result of all three steps matches. From our point of view Blaze works as expected.

    Taking a closer look at your output, there are a couple of strange details:

    ...
    [operator()] Before third calculation: 0, 0 value is 0.000000. 
    [operator()] Cast, no temporary, but with recalculation: 0, 0 value is 1795203.675000. Second calculation: 0.000000
    [operator()] Before third calculation: 0, 1 value is 1795203.675000. 
    [operator()] Cast, no temporary, but with recalculation: 0, 1 value is 28351239.800000. Second calculation: 0.000000
    ...
    

    The first line accesses ret(0,0) and prints 0.0. The second line accesses the same value again, but comes up with a value of 1795203.675 without a modification of the value in-between. The third line accesses ret(0,1) and comes up with the same value as ret(0,0). This suggests that the function in the minimum example is not identical to the function you are using or that something else is working with the symmetric matrix (multiple threads)?

    In order to enable us to reproduce the problem could you please provide information on your input matrix, the used data types (MatrixType, FloatType, ...), and the number of threads?

    Best regards,

    Klaus!

  2. Daniel Baker reporter

    Hi Klaus,

    Thanks for looking!

    I agree, that is the behavior I would expect.

    I'm running the same code with the same constants, with FloatType=float and MatrixType=DynamicMatrix<float, rowMajor>, and with the number of threads=1.

    My output is still different, though the same numbers are output at at least one point:

    I finally replaced my LOG_INFO (which returns std::fprintf(stderr, "[%s]" str, func, [args])) with cerr, and the results display as they should. It seems that the problem is that the problem only occurs when outputting with fprintf:

            cerr << "rows: " << a.rows() << '\n';
            if(ret.rows() != a.rows()) ret.resize(a.rows());
            assert(ret.rows() == a.rows());
            assert(ret.columns() == a.rows());
            const size_t len(a.rows());
            for(size_t i(0); i < len; ++i) {
                for(size_t j = i; j < len; ++j) {
                    ret(i, j) = static_cast<FloatType>(dot(row(a, i), row(a, j))) + c_; 
                    std::fprintf(stderr, "[%s] Value at %zu, %zu is %f\n", __func__, i, j, ret(i, j));
                    cerr << "Value at " << i << ", " << j << " is " << ret(i, j) << '\n';
                }   
            }   
            cerr << "ret is \n" << ret;
            ret = tanh(ret * k_);
            cerr << "after tanh\n" << ret;
            return ret;
    

    emits

    [operator()] Value at 0, 0 is 0.000000
    Value at 0, 0 is 8.05
    [operator()] Value at 0, 1 is 0.000000
    Value at 0, 1 is 15.31
    [operator()] Value at 0, 2 is 0.000000
    Value at 0, 2 is 22.57
    [operator()] Value at 1, 1 is 0.000000
    Value at 1, 1 is 32.25
    [operator()] Value at 1, 2 is 0.000000
    Value at 1, 2 is 49.19
    [operator()] Value at 2, 2 is 0.000000
    Value at 2, 2 is 75.81
    ret is 
    (         8.05        15.31        22.57 )
    (        15.31        32.25        49.19 )
    (        22.57        49.19        75.81 )
    after tanh
    (            1            1            1 )
    (            1            1            1 )
    (            1            1            1 )
    

    Thanks for your help! I still don't know why fprintf isn't performing as expected, but I'm glad to know that it was the printing of the values, not the generation of them that was at issue. Please go ahead and close this; I still have no idea why fprintf acted up, but I'm glad Blaze is working.

  3. Log in to comment