Skip to content

Commit

Permalink
cuda: starting point for using Stream for thread-safe concurrency whe…
Browse files Browse the repository at this point in the history
…n using GPU

Signed-off-by: deadprogram <[email protected]>
  • Loading branch information
deadprogram committed Aug 12, 2021
1 parent e118065 commit 0385a5b
Show file tree
Hide file tree
Showing 24 changed files with 899 additions and 97 deletions.
4 changes: 2 additions & 2 deletions Dockerfile.gpu
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# to build this docker image:
# docker build -f Dockerfile.gpu .
FROM gocv/opencv:4.5.3-gpu AS gocv-gpu
FROM gocv/opencv:4.5.3-gpu-cuda-11 AS gocv-gpu

ENV GOPATH /go

COPY . /go/src/gocv.io/x/gocv/

WORKDIR /go/src/gocv.io/x/gocv
RUN go build -tags example -o /build/gocv_cuda_version ./cmd/cuda/
RUN go build -tags cuda -o /build/gocv_cuda_version ./cmd/cuda/

CMD ["/build/gocv_cuda_version"]
25 changes: 19 additions & 6 deletions cuda/arithm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,27 @@
#include "arithm.h"
#include <string.h>

void GpuAbs(GpuMat src, GpuMat dst) {
cv::cuda::abs(*src, *dst);
void GpuAbs(GpuMat src, GpuMat dst, Stream s) {
if (s == NULL) {
cv::cuda::abs(*src, *dst);
return;
}
cv::cuda::abs(*src, *dst, *s);
}

void GpuThreshold(GpuMat src, GpuMat dst, double thresh, double maxval, int typ) {
cv::cuda::threshold(*src, *dst, thresh, maxval, typ);
void GpuThreshold(GpuMat src, GpuMat dst, double thresh, double maxval, int typ, Stream s) {
if (s == NULL) {
cv::cuda::threshold(*src, *dst, thresh, maxval, typ);
return;
}

cv::cuda::threshold(*src, *dst, thresh, maxval, typ, *s);
}

void GpuFlip(GpuMat src, GpuMat dst, int flipCode) {
cv::cuda::flip(*src, *dst, flipCode);
void GpuFlip(GpuMat src, GpuMat dst, int flipCode, Stream s) {
if (s == NULL) {
cv::cuda::flip(*src, *dst, flipCode);
return;
}
cv::cuda::flip(*src, *dst, flipCode, *s);
}
36 changes: 33 additions & 3 deletions cuda/arithm.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,17 @@ import "gocv.io/x/gocv"
// https://docs.opencv.org/master/d8/d34/group__cudaarithm__elem.html#ga54a72bd772494ab34d05406fd76df2b6
//
func Abs(src GpuMat, dst *GpuMat) {
C.GpuAbs(src.p, dst.p)
C.GpuAbs(src.p, dst.p, nil)
}

// AbsWithStream computes an absolute value of each matrix element
// using a Stream for concurrency.
//
// For further details, please see:
// https://docs.opencv.org/master/d8/d34/group__cudaarithm__elem.html#ga54a72bd772494ab34d05406fd76df2b6
//
func AbsWithStream(src GpuMat, dst *GpuMat, stream Stream) {
C.GpuAbs(src.p, dst.p, stream.p)
}

// Threshold applies a fixed-level threshold to each array element.
Expand All @@ -25,7 +35,17 @@ func Abs(src GpuMat, dst *GpuMat) {
// https://docs.opencv.org/master/d8/d34/group__cudaarithm__elem.html#ga40f1c94ae9a9456df3cad48e3cb008e1
//
func Threshold(src GpuMat, dst *GpuMat, thresh, maxval float64, typ gocv.ThresholdType) {
C.GpuThreshold(src.p, dst.p, C.double(thresh), C.double(maxval), C.int(typ))
C.GpuThreshold(src.p, dst.p, C.double(thresh), C.double(maxval), C.int(typ), nil)
}

// ThresholdWithStream applies a fixed-level threshold to each array element
// using a Stream for concurrency.
//
// For further details, please see:
// https://docs.opencv.org/master/d8/d34/group__cudaarithm__elem.html#ga40f1c94ae9a9456df3cad48e3cb008e1
//
func ThresholdWithStream(src GpuMat, dst *GpuMat, thresh, maxval float64, typ gocv.ThresholdType, s Stream) {
C.GpuThreshold(src.p, dst.p, C.double(thresh), C.double(maxval), C.int(typ), s.p)
}

// Flip flips a 2D matrix around vertical, horizontal, or both axes.
Expand All @@ -34,5 +54,15 @@ func Threshold(src GpuMat, dst *GpuMat, thresh, maxval float64, typ gocv.Thresho
// https://docs.opencv.org/master/de/d09/group__cudaarithm__core.html#ga4d0a3f2b46e8f0f1ec2b5ac178dcd871
//
func Flip(src GpuMat, dst *GpuMat, flipCode int) {
C.GpuFlip(src.p, dst.p, C.int(flipCode))
C.GpuFlip(src.p, dst.p, C.int(flipCode), nil)
}

// FlipWithStream flips a 2D matrix around vertical, horizontal, or both axes
// using a Stream for concurrency.
//
// For further details, please see:
// https://docs.opencv.org/master/de/d09/group__cudaarithm__core.html#ga4d0a3f2b46e8f0f1ec2b5ac178dcd871
//
func FlipWithStream(src GpuMat, dst *GpuMat, flipCode int, stream Stream) {
C.GpuFlip(src.p, dst.p, C.int(flipCode), stream.p)
}
6 changes: 3 additions & 3 deletions cuda/arithm.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ extern "C" {
#endif
#include "cuda.h"

void GpuAbs(GpuMat src, GpuMat dst);
void GpuThreshold(GpuMat src, GpuMat dst, double thresh, double maxval, int typ);
void GpuFlip(GpuMat src, GpuMat dst, int flipCode);
void GpuAbs(GpuMat src, GpuMat dst, Stream s);
void GpuThreshold(GpuMat src, GpuMat dst, double thresh, double maxval, int typ, Stream s);
void GpuFlip(GpuMat src, GpuMat dst, int flipCode, Stream s);

#ifdef __cplusplus
}
Expand Down
72 changes: 72 additions & 0 deletions cuda/arithm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,30 @@ func TestAbs(t *testing.T) {
}
}

func TestAbsWithStream(t *testing.T) {
src := gocv.IMRead("../images/gocvlogo.jpg", gocv.IMReadColor)
if src.Empty() {
t.Error("Invalid read of Mat in Abs test")
}
defer src.Close()

var cimg, dimg, s = NewGpuMat(), NewGpuMat(), NewStream()
defer cimg.Close()
defer dimg.Close()
defer s.Close()

cimg.Upload(src)

dest := gocv.NewMat()
defer dest.Close()

AbsWithStream(cimg, &dimg, s)
dimg.Download(&dest)
if dest.Empty() || src.Rows() != dest.Rows() || src.Cols() != dest.Cols() {
t.Error("Invalid Abs test")
}
}

func TestThreshold(t *testing.T) {
src := gocv.IMRead("../images/gocvlogo.jpg", gocv.IMReadColor)
if src.Empty() {
Expand All @@ -52,6 +76,30 @@ func TestThreshold(t *testing.T) {
}
}

func TestThresholdWithStream(t *testing.T) {
src := gocv.IMRead("../images/gocvlogo.jpg", gocv.IMReadColor)
if src.Empty() {
t.Error("Invalid read of Mat in Threshold test")
}
defer src.Close()

var cimg, dimg, s = NewGpuMat(), NewGpuMat(), NewStream()
defer cimg.Close()
defer dimg.Close()
defer s.Close()

cimg.Upload(src)

dest := gocv.NewMat()
defer dest.Close()

ThresholdWithStream(cimg, &dimg, 25, 255, gocv.ThresholdBinary, s)
dimg.Download(&dest)
if dest.Empty() || src.Rows() != dest.Rows() || src.Cols() != dest.Cols() {
t.Error("Invalid Threshold test")
}
}

func TestFlip(t *testing.T) {
src := gocv.IMRead("../images/gocvlogo.jpg", gocv.IMReadColor)
if src.Empty() {
Expand All @@ -74,3 +122,27 @@ func TestFlip(t *testing.T) {
t.Error("Invalid Flip test")
}
}

func TestFlipWithStream(t *testing.T) {
src := gocv.IMRead("../images/gocvlogo.jpg", gocv.IMReadColor)
if src.Empty() {
t.Error("Invalid read of Mat in Flip test")
}
defer src.Close()

var cimg, dimg, s = NewGpuMat(), NewGpuMat(), NewStream()
defer cimg.Close()
defer dimg.Close()
defer s.Close()

cimg.Upload(src)

dest := gocv.NewMat()
defer dest.Close()

FlipWithStream(cimg, &dimg, 0, s)
dimg.Download(&dest)
if dest.Empty() || src.Rows() != dest.Rows() || src.Cols() != dest.Cols() {
t.Error("Invalid Flip test")
}
}
16 changes: 12 additions & 4 deletions cuda/bgsegm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,12 @@ void CudaBackgroundSubtractorMOG2_Close(CudaBackgroundSubtractorMOG2 b) {
delete b;
}

void CudaBackgroundSubtractorMOG2_Apply(CudaBackgroundSubtractorMOG2 b, GpuMat src, GpuMat dst) {
(*b)->apply(*src, *dst);
void CudaBackgroundSubtractorMOG2_Apply(CudaBackgroundSubtractorMOG2 b, GpuMat src, GpuMat dst, Stream s) {
if (s == NULL) {
(*b)->apply(*src, *dst);
return;
}
(*b)->apply(*src, *dst, -1.0, *s);
}

CudaBackgroundSubtractorMOG CudaBackgroundSubtractorMOG_Create() {
Expand All @@ -20,6 +24,10 @@ void CudaBackgroundSubtractorMOG_Close(CudaBackgroundSubtractorMOG b) {
delete b;
}

void CudaBackgroundSubtractorMOG_Apply(CudaBackgroundSubtractorMOG b, GpuMat src, GpuMat dst) {
(*b)->apply(*src, *dst);
void CudaBackgroundSubtractorMOG_Apply(CudaBackgroundSubtractorMOG b, GpuMat src, GpuMat dst, Stream s) {
if (s == NULL) {
(*b)->apply(*src, *dst);
return;
}
(*b)->apply(*src, *dst, -1.0, *s);
}
26 changes: 24 additions & 2 deletions cuda/bgsegm.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,18 @@ func (b *BackgroundSubtractorMOG2) Close() error {
// https://docs.opencv.org/master/df/d23/classcv_1_1cuda_1_1BackgroundSubtractorMOG2.html#a92408f07bf1268c1b778cb186b3113b0
//
func (b *BackgroundSubtractorMOG2) Apply(src GpuMat, dst *GpuMat) {
C.CudaBackgroundSubtractorMOG2_Apply((C.CudaBackgroundSubtractorMOG2)(b.p), src.p, dst.p)
C.CudaBackgroundSubtractorMOG2_Apply((C.CudaBackgroundSubtractorMOG2)(b.p), src.p, dst.p, nil)
return
}

// ApplyWithStream computes a foreground mask using the current BackgroundSubtractorMOG2
// using a Stream for concurrency.
//
// For further details, please see:
// https://docs.opencv.org/master/df/d23/classcv_1_1cuda_1_1BackgroundSubtractorMOG2.html#a92408f07bf1268c1b778cb186b3113b0
//
func (b *BackgroundSubtractorMOG2) ApplyWithStream(src GpuMat, dst *GpuMat, s Stream) {
C.CudaBackgroundSubtractorMOG2_Apply((C.CudaBackgroundSubtractorMOG2)(b.p), src.p, dst.p, s.p)
return
}

Expand Down Expand Up @@ -71,6 +82,17 @@ func (b *BackgroundSubtractorMOG) Close() error {
// https://docs.opencv.org/master/d1/dfe/classcv_1_1cuda_1_1BackgroundSubtractorMOG.html#a8f52d2f7abd1c77c84243efc53972cbf
//
func (b *BackgroundSubtractorMOG) Apply(src GpuMat, dst *GpuMat) {
C.CudaBackgroundSubtractorMOG_Apply((C.CudaBackgroundSubtractorMOG)(b.p), src.p, dst.p)
C.CudaBackgroundSubtractorMOG_Apply((C.CudaBackgroundSubtractorMOG)(b.p), src.p, dst.p, nil)
return
}

// ApplyWithStream computes a foreground mask using the current BackgroundSubtractorMOG
// using a Stream for concurrency.
//
// For further details, please see:
// https://docs.opencv.org/master/d1/dfe/classcv_1_1cuda_1_1BackgroundSubtractorMOG.html#a8f52d2f7abd1c77c84243efc53972cbf
//
func (b *BackgroundSubtractorMOG) ApplyWithStream(src GpuMat, dst *GpuMat, s Stream) {
C.CudaBackgroundSubtractorMOG_Apply((C.CudaBackgroundSubtractorMOG)(b.p), src.p, dst.p, s.p)
return
}
4 changes: 2 additions & 2 deletions cuda/bgsegm.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ typedef void* CudaBackgroundSubtractorMOG;

CudaBackgroundSubtractorMOG2 CudaBackgroundSubtractorMOG2_Create();
void CudaBackgroundSubtractorMOG2_Close(CudaBackgroundSubtractorMOG2 b);
void CudaBackgroundSubtractorMOG2_Apply(CudaBackgroundSubtractorMOG2 b, GpuMat src, GpuMat dst);
void CudaBackgroundSubtractorMOG2_Apply(CudaBackgroundSubtractorMOG2 b, GpuMat src, GpuMat dst, Stream s);

CudaBackgroundSubtractorMOG CudaBackgroundSubtractorMOG_Create();
void CudaBackgroundSubtractorMOG_Close(CudaBackgroundSubtractorMOG b);
void CudaBackgroundSubtractorMOG_Apply(CudaBackgroundSubtractorMOG b, GpuMat src, GpuMat dst);
void CudaBackgroundSubtractorMOG_Apply(CudaBackgroundSubtractorMOG b, GpuMat src, GpuMat dst, Stream s);

#ifdef __cplusplus
}
Expand Down
61 changes: 60 additions & 1 deletion cuda/bgsegm_test.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package cuda

import (
"gocv.io/x/gocv"
"testing"

"gocv.io/x/gocv"
)

func TestCudaMOG2(t *testing.T) {
Expand Down Expand Up @@ -33,6 +34,35 @@ func TestCudaMOG2(t *testing.T) {
}
}

func TestCudaMOG2WithStream(t *testing.T) {
img := gocv.IMRead("../images/face.jpg", gocv.IMReadColor)
if img.Empty() {
t.Error("Invalid Mat in CudaMOG2 test")
}
defer img.Close()

var cimg, dimg, s = NewGpuMat(), NewGpuMat(), NewStream()
defer cimg.Close()
defer dimg.Close()
defer s.Close()

cimg.Upload(img)

dst := gocv.NewMat()
defer dst.Close()

mog2 := NewBackgroundSubtractorMOG2()
defer mog2.Close()

mog2.ApplyWithStream(cimg, &dimg, s)

dimg.Download(&dst)

if dst.Empty() {
t.Error("Error in TestCudaMOG2 test")
}
}

func TestCudaMOG(t *testing.T) {
img := gocv.IMRead("../images/face.jpg", gocv.IMReadColor)
if img.Empty() {
Expand Down Expand Up @@ -60,3 +90,32 @@ func TestCudaMOG(t *testing.T) {
t.Error("Error in TestCudaMOG test")
}
}

func TestCudaMOGWithStream(t *testing.T) {
img := gocv.IMRead("../images/face.jpg", gocv.IMReadColor)
if img.Empty() {
t.Error("Invalid Mat in CudaMOG test")
}
defer img.Close()

var cimg, dimg, s = NewGpuMat(), NewGpuMat(), NewStream()
defer cimg.Close()
defer dimg.Close()
defer s.Close()

cimg.Upload(img)

dst := gocv.NewMat()
defer dst.Close()

mog2 := NewBackgroundSubtractorMOG()
defer mog2.Close()

mog2.ApplyWithStream(cimg, &dimg, s)

dimg.Download(&dst)

if dst.Empty() {
t.Error("Error in TestCudaMOG test")
}
}
8 changes: 8 additions & 0 deletions cuda/cuda.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,11 @@ int GpuMat_Channels(GpuMat m) {
int GpuMat_Type(GpuMat m) {
return m->type();
}

Stream Stream_New() {
return new cv::cuda::Stream();
}

void Stream_Close(Stream s){
delete s;
}
Loading

0 comments on commit 0385a5b

Please sign in to comment.