link to the full code i write. https://github.com/oderoi/Mojo/blob/main/examples/matrix.mojo
#Can anyone help me to solve this error.
9 messages · Page 1 of 1 (latest)
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)
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.
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.
ok, thank you so much
Wait, I completely missed something
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