#Can anyone help me to solve this error.

9 messages · Page 1 of 1 (latest)

rapid mason
pale quest
#

It looks like a double free, you're calling A.data.free() and etc. for all the matrices after the benchmark is run, but when they get destructed, each __del__ gets called, freeing the pointers again. You can keep the matrices alive a different way, like I just changed those A.data.free() calls to _ = A.rows or quite literally anything that uses the matrices, or remove the free call in __del__. I think the first option is "better" practice for now.

This is what I ran, and it appears to work as expected.

from random import rand
from memory import memset, memset_zero
from memory.unsafe import DTypePointer, Pointer
import benchmark

alias type=DType.float64

struct Matrix:
    var data: DTypePointer[type]
    var rows: Int
    var cols: Int

    #initisalize zeroing all values
    fn __init__(inout self, rows: Int, cols: Int):
        self.data = DTypePointer[type].alloc(rows * cols)
        memset_zero(self.data, rows*cols)
        self.rows = rows
        self.cols = cols

    #initialize taking a pointer, don't set any elements    
    fn __init__(inout self, rows: Int, cols: Int , data: DTypePointer[DType.float64]):
        self.data=data
        self.cols=cols
        self.rows=rows

    #Initialize with random values

    @staticmethod
    fn rand(rows: Int, cols: Int)-> Self:
        let data = DTypePointer[type].alloc(rows * cols)
        rand(data, rows*cols)
        return Self(rows,  cols, data)

    fn __getitem__(self, y: Int, x: Int)->Float64:
        return self.load[1](y, x)

    fn __setitem__(self, y: Int, x: Int, val: Float64):
        return self.store[1](y,  x, val)

    fn load[nelts: Int](self, y: Int, x: Int) -> SIMD[DType.float64, nelts]:
        return self.data.simd_load[nelts](y * self.cols + x)

    fn store[nelts: Int](self, y: Int, x: Int, val: SIMD[DType.float64, nelts]):
        return self.data.simd_store[nelts](y * self.cols + x, val)

    fn __del__(owned self):
        self.data.free()

   
    fn print(self):
        print_no_newline("[")
        for i in range(self.rows*self.cols):
            if i > 0:
                print_no_newline(", ")
            print_no_newline(self.data.load(i))
        print("]")
        
# Note that C, A, and B have types.
fn matmul_naive(C: Matrix, A: Matrix, B: Matrix):
    for m in range(C.rows):
        for k in range(A.cols):
            for n in range(C.cols):
                C[m, n] += A[m, k] * B[k, n]



fn main():
    alias M = 1024
    alias N = 1024
    alias K = 1024

    @always_inline
    fn bench[
        func: fn (Matrix, Matrix, Matrix) -> None](base_gflops: Float64):
        var C = Matrix(M, N)
        var A = Matrix.rand(M, K)
        var B = Matrix.rand(K, N)

        @always_inline
        @parameter
        fn test_fn():
            _ = func(C, A, B)

        let secs = benchmark.run[test_fn](max_runtime_secs=1).mean()
        # Prevent the matrices from being freed before the benchmark run
        _ = A.rows
        _ = B.rows
        _ = C.rows
        let gflops = ((2 * M * N * K) / secs) / 1e9
        #let speedup: Float64 = gflops / base_gflops
        print(gflops, "GFLOP/s")
        #print(gflops, "GFLOP/s, a", speedup, "x speedup over Python")

    bench[matmul_naive](Float64)
rapid mason
#

thank you , this helps ,...

Also , if i uncomment this :
#let speedup: Float64 = gflops / base_gflops
#print(gflops, "GFLOP/s, a", speedup, "x speedup over Python")

and add :
print(gflops, "GFLOP/s", speedup, "speedup")

I get that error :

can you help me with that as well if you may.
Thank you.

pale quest
#

Wow, this is a bad bug. Looks like an actual language one, there's something bad happening under the hood. So far I can't see a way to get around it, would be good to create an issue on the Github https://github.com/modularml/mojo/issues. I took a look and didn't see anything similar to this previously reported.

rapid mason
#

ok, thank you so much

pale quest
#

The reason is because you're passing the type Float64 into bench at the end, when it really expects something of the type Float64, like 1.0 or a variable

#

I guess it's true the compiler should emit a better error than this, but changing that last Float64 to something like 0.5 (I don't know the actual base GFLOPS that Python runs this at) works

#

I think you can go ahead and still make an issue, but make it instead about a better error in this case. Because something like:

fn add(a: Int) -> Int:
    return a + 1

fn main():
    print(a(Int))

should probably produce an error less cryptic