func TestArrayCopy(test *testing.T) { runtime.LockOSThread() // fail test on panic, do not crash //defer func() { // if err := recover(); err != nil { // test.Error(err) // } //}() size := []int{4, 8, 16} host1, host2 := host.NewArray(3, size), host.NewArray(3, size) dev1, dev2 := NewArray(3, size), NewArray(3, size) defer dev1.Free() defer dev2.Free() l1 := host1.List for i := range l1 { l1[i] = float64(i) } dev1.CopyFromHost(host1) dev2.CopyFromDevice(dev1) dev2.CopyToHost(host2) l2 := host2.List for i := range l1 { if l2[i] != float64(i) { if !test.Failed() { test.Error("expected", i, "got:", l2[i]) } } } }
// Set the multiplier of a MASK or the value of a VALUE func (q *Quant) SetValue(val []float64) { //Debug("SetValue", q.name, val) //~ checkKinds(q, MASK, VALUE) checkComp(q, len(val)) if q.kind == MASK || q.kind == VALUE { for i, v := range val { q.multiplier[i] = v } } else if q.kind == FIELD { q.multiplier = ones(q.nComp) // use q.Buffer instead? tempField := host.NewArray(q.nComp, q.array.Size3D()) for c := 0; c < q.nComp; c++ { for i := 0; i < q.array.Size3D()[X]; i++ { for j := 0; j < q.array.Size3D()[Y]; j++ { for k := 0; k < q.array.Size3D()[Z]; k++ { tempField.Array[c][i][j][k] = float64(val[c]) } } } } q.SetField(tempField) // not sure whenever tempBuffer will be destroyed by the GC? } else { panic(InputErr(q.name + " is not " + MASK.String() + " or " + FIELD.String() + " or " + VALUE.String() + " but " + q.kind.String())) } q.Verify() q.Invalidate() //! }
func genWindow(size []int) *host.Array { window := host.NewArray(1, size) for i := 0; i < size[0]; i++ { val0 := 1.0 if size[0] > 16 { arg0 := float64(i) / float64(size[0]-1) val0 = gauss(arg0, 0.4) } for j := 0; j < size[1]; j++ { val1 := 1.0 if size[1] > 16 { arg1 := float64(j) / float64(size[1]-1) val1 = gauss(arg1, 0.4) } for k := 0; k < size[2]; k++ { val2 := 1.0 if size[2] > 16 { arg2 := float64(k) / float64(size[2]-1) val2 = gauss(arg2, 0.4) } window.Array[0][i][j][k] = float64(val0 * val1 * val2) } } } return window }
// Converts a json vector array to a host.Array. // Also swaps XYZ - ZYX convention // TODO: works only for 4D vector arrays func jsonToHostArray(v interface{}) *host.Array { defer func() { err := recover() if err != nil { panic(IOErr(fmt.Sprint("Error parsing json array: ", ShortPrint(v), "\ncause: ", err))) } }() err := false // determine array size as {len(v), len(v[0]), len(v[0][0]), ...} var size [4]int v2 := v for i := range size { if arr, ok := v2.([]interface{}); ok { size[i] = len(arr) if size[i] == 0 { err = true break } v2 = arr[0] } else { err = true break } } if err { panic(IOErr(fmt.Sprint("Array with invalid size:", ShortPrint(v)))) } size3D := size[1:] arr := host.NewArray(size[0], []int{size3D[X], size3D[Y], size3D[Z]}) a := arr.Array va := v.([]interface{}) for c := range a { va_c := va[c].([]interface{}) for i := range a[c] { va_ci := va_c[i].([]interface{}) for j := range a[c][i] { va_cij := va_ci[j].([]interface{}) for k := range a[c][i][j] { a[c][i][j][k] = float64(va_cij[k].(float64)) // convert XYZ-ZYX, works only for 3D } } } } runtime.GC() // a LOT of garbage has been made return convertXYZ(arr) }
func BenchmarkReduceSumCPU(b *testing.B) { b.StopTimer() size := bigsize() a := host.NewArray(3, size) b.SetBytes(int64(a.Len()) * SIZEOF_FLOAT) b.StartTimer() for i := 0; i < b.N; i++ { var cpusum float64 for _, num := range a.List { cpusum += float64(num) } } }
// Should init to zeros func TestArrayInit(test *testing.T) { runtime.LockOSThread() // fail test on panic, do not crash //defer func() { // if err := recover(); err != nil { // test.Error(err) // } //}() size := []int{4, 8, 16} host1 := host.NewArray(3, size) dev1 := NewArray(3, size) defer dev1.Free() fmt.Printf("%+v\n", dev1) if dev1.Len() != 3*Prod(size) { if !test.Failed() { test.Error("Len(): ", dev1.Len(), "expected: ", 3*Prod(size)) } } if dev1.PartLen4D() != 3*Prod(size)/NDevice() { test.Fail() } if dev1.PartLen3D() != Prod(size)/NDevice() { test.Fail() } l1 := host1.List for i := range l1 { l1[i] = float64(i) } dev1.CopyToHost(host1) //host1.CopyFromDevice(dev1) for i := range l1 { if l1[i] != 0 { if !test.Failed() { test.Error(l1[i], "!=0") } } } }
// Convert mumax's internal ZYX convention to userspace XYZ. func convertXYZ(arr *host.Array) *host.Array { s := arr.Size3D n := arr.NComp() a := arr.Array transp := host.NewArray(n, []int{s[Z], s[Y], s[X]}) t := transp.Array for c := 0; c < n; c++ { for i := 0; i < s[X]; i++ { for j := 0; j < s[Y]; j++ { for k := 0; k < s[Z]; k++ { t[(n-1)-c][k][j][i] = a[c][i][j][k] } } } } runtime.GC() // a LOT of garbage has been made return transp }
// Returns a new host array of size size2, re-sized from the input array by nearest-neighbor interpolation. func Resample(in *host.Array, size2 []int) *host.Array { Assert(len(size2) == 3) out := host.NewArray(in.NComp(), size2) out_a := out.Array in_a := in.Array size1 := in.Size3D for c := range out_a { for i := range out_a[c] { i1 := (i * size1[X]) / size2[X] for j := range out_a[0][i] { j1 := (j * size1[Y]) / size2[Y] for k := range out_a[0][i][j] { k1 := (k * size1[Z]) / size2[Z] out_a[c][i][j][k] = in_a[c][i1][j1][k1] } } } } return out }
func ReadPNG(fname string) *host.Array { in, err := os.Open(fname) CheckIO(err) img, err2 := png.Decode(in) CheckIO(err2) width := img.Bounds().Max.X height := img.Bounds().Max.Y inside := host.NewArray(1, []int{1, height, width}) for i := 0; i < height; i++ { for j := 0; j < width; j++ { r, g, b, _ := img.At(j, height-1-i).RGBA() if r+g+b < (0xFFFF*3)/2 { inside.Array[0][0][i][j] = 1 } } } return inside }
// Extract real or imaginary parts, copy them from src to dst. // In the meanwhile, check if the other parts are nearly zero // and scale the kernel to compensate for unnormalized FFTs. // real_imag = 0: real parts // real_imag = 1: imag parts func extract(src *host.Array) *host.Array { sx := src.Size3D[X]/2 + 1 // antisymmetric sy := src.Size3D[Y]/2 + 1 // antisymmetric sz := src.Size3D[Z] / 2 // only real parts should be stored, the value of the imaginary part should stay below the zero threshould dst := host.NewArray(src.NComp(), []int{sx, sy, sz}) dstArray := dst.Array srcArray := src.Array // Normally, the FFT'ed kernel is purely real because of symmetry, // so we only store the real parts... maxImg := float64(0.) maxReal := float64(0.) for c := range dstArray { for k := range dstArray[c] { for j := range dstArray[c][k] { for i := range dstArray[c][k][j] { dstArray[c][k][j][i] = srcArray[c][k][j][2*i] if Abs32(srcArray[c][k][j][2*i+1]) > maxImg { maxImg = Abs32(srcArray[c][k][j][2*i+1]) } if Abs32(srcArray[c][k][j][2*i+0]) > maxReal { maxReal = Abs32(srcArray[c][k][j][2*i+0]) } } } } } // ...however, we check that the imaginary parts are nearly zero, // just to be sure we did not make a mistake during kernel creation. Debug("FFT Kernel max real part", 0, ":", maxReal) Debug("FFT Kernel max imag part", 1, ":", maxImg) Debug("FFT Kernel max imag/real part=", maxImg/maxReal) if maxImg/maxReal > 1e-12 { // TODO: is this reasonable? panic(BugF("FFT Kernel max bad/good part=", maxImg/maxReal)) } return dst }
// DEBUG: Make a freshly allocated copy on the host. func (src *Array) LocalCopy() *host.Array { dst := host.NewArray(src.NComp(), src.Size3D()) src.CopyToHost(dst) return dst }