- edited description
Issue with dot product: only calculating at second request to calculate
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)
-
reporter -
Hi dnbh!
I tried to reproduce your problem by using both
DynamicMatrix<float,rowMajor>
andCompressedMatrix<float,rowMajor>
forMatrixType
,2.0F
forc_
and3.0F
fork_
. 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 arbitrary3x2
input matrix fora
:( 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 prints0.0
. The second line accesses the same value again, but comes up with a value of1795203.675
without a modification of the value in-between. The third line accessesret(0,1)
and comes up with the same value asret(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!
-
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.
-
- changed status to wontfix
Hi dnbh!
Thanks for letting us know.
Best regards,
Klaus!
- Log in to comment