StanfordAHA / Halide-to-Hardware

Other
74 stars 12 forks source link

Possible incorrect code behavior by overaggressive optimizations #140

Open wyanzhao opened 1 year ago

wyanzhao commented 1 year ago

Hi, I wrote the following simple algorithm:

        void create_algorithm() {  
            Expr a(1);
            Expr b(2);
            Expr c(3);
            Expr d(2);

            hw_output(x) = input(x) + (((a* b) - c) / d);
            output(x) = hw_output(x);
        }

I found when a, b, c,d are in some special values, like the above code. Halide-to-Hardware produces inconsistent results with the C reference results. Belows are my testing code:

    Buffer<int32_t> input(1);
    Buffer<int32_t> out_native(1);

    Buffer<int32_t> c_results(1);

    for (int y = 0; y <1; y++) {
        input(y) = (int32_t)rand();
    }

    example(input, out_native);

    int32_t constant = (((((int32_t)1 * (int32_t)2) - (int32_t)3) / (int32_t)2));
    for (int y = 0; y <1; y++) {
        c_results(y) = input(y) + constant;
    }

    bool success = true;
    for (int y = 0; y <1; y++) {
        if (out_native(y) != c_results(y))
            success = false;
    }

    if(success) {
        printf("[APP] Test Passed!\n");
    } else {
        printf("[APP] Test Failed!\n");
        return 1;
    }

Above test will fail.

jeffsetter commented 1 year ago

Can you give an example input value, native output, and c result that you encountered?

wyanzhao commented 1 year ago

Hi, here's my testing code:

int main(int argc, char *argv[]) {

    Buffer<int32_t> input(1);
    Buffer<int32_t> out_native(1);

    Buffer<int32_t> c_results(1);

    for (int y = 0; y <1; y++) {
        input(y) = (int32_t)rand();
    }

    input(0) = 17;
    out_native(0) = 0;
    c_results(0) = 0;

    example(input, out_native);
    printf("[APP] Finished running native code\n");

    int32_t constant = (((((int32_t)1 * (int32_t)2) - (int32_t)3) / (int32_t)2));
    for (int y = 0; y <1; y++) {
        c_results(y) = input(y) + constant;
    }

    bool success = true;
    for (int y = 0; y <1; y++) {
        if (out_native(y) != c_results(y))
            success = false;
    }

    std::cout<< "input(0):"<< input(0)<< "\n";
    std::cout<< "out_native(0):"<< out_native(0)<< "\n";
    std::cout<< "c_results(0):"<< c_results(0)<< "\n";

    if(success) {
        printf("[APP] Test Passed!\n");
    } else {
        printf("[APP] Test Failed!\n");
        return 1;
    }

    return 0;
}

When the input is 17, out_native and c_results are 0. The terminal output is:

input(0):17
out_native(0):16
c_results(0):17
[APP] Test Failed!
jeffsetter commented 1 year ago

I think this may be from the division by 2 rounding to zero rather than rounding away from zero.