Closed sakalauskas closed 3 years ago
@sakalauskas Awesome - I dont know how it gets down to 30 frames per second on normal CUDA using the jetson reference apps... but I really like this :D
Regards, Richard
Good stuff! Thanks!
Has anyone tried this recently or I may be missing a step? Tested on a NVIDIA Jetson Nano 2GB Developer Kit and getting the following:
Step 40/53 : RUN make
---> Running in 5e7e4c0843a2
GO111MODULE=off go get github.com/gogo/protobuf/proto
go: downloading google.golang.org/grpc v1.30.0
go: downloading github.com/spf13/cobra v1.0.0
go: downloading golang.org/x/image v0.0.0-20200618115811-c13761719519
go: downloading github.com/lmittmann/ppm v1.0.0
go: downloading github.com/spf13/viper v1.7.0
go: downloading golang.org/x/net v0.0.0-20200602114024-627f9648deb9
go: downloading github.com/grpc-ecosystem/grpc-gateway v1.14.6
go: downloading github.com/pelletier/go-toml v1.8.0
go: downloading github.com/grpc-ecosystem/go-grpc-middleware v1.2.0
go: downloading github.com/hashicorp/hcl v1.0.0
go: downloading github.com/snowzach/certtools v1.0.2
go: downloading github.com/fsnotify/fsnotify v1.4.9
go: downloading github.com/gogo/protobuf v1.3.1
go: downloading github.com/go-chi/cors v1.1.1
go: downloading gopkg.in/yaml.v2 v2.3.0
go: downloading github.com/tensorflow/tensorflow v2.0.0+incompatible
go: downloading github.com/golang/protobuf v1.4.2
go: downloading github.com/subosito/gotenv v1.2.0
go: downloading gopkg.in/ini.v1 v1.57.0
go: downloading github.com/mitchellh/mapstructure v1.3.2
go: downloading github.com/spf13/pflag v1.0.5
go: downloading github.com/go-chi/chi v4.1.2+incompatible
go: downloading github.com/spf13/jwalterweatherman v1.1.0
go: downloading google.golang.org/genproto v0.0.0-20200623002339-fbb79eadd5eb
go: downloading github.com/go-chi/render v1.0.1
go: downloading google.golang.org/protobuf v1.24.0
go: downloading go.uber.org/zap v1.15.0
go: downloading github.com/spf13/cast v1.3.1
go: downloading golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4
go: downloading golang.org/x/text v0.3.3
go: downloading github.com/blendle/zapdriver v1.3.1
go: downloading go.uber.org/atomic v1.6.0
go: downloading github.com/magiconair/properties v1.8.1
go: downloading github.com/spf13/afero v1.3.0
go: downloading go.uber.org/multierr v1.5.0
go get github.com/gogo/protobuf/protoc-gen-gogoslick
go: found github.com/gogo/protobuf/protoc-gen-gogoslick in github.com/gogo/protobuf v1.3.1
go get github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway
go: downloading github.com/grpc-ecosystem/grpc-gateway v1.16.0
go: found github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway in github.com/grpc-ecosystem/grpc-gateway v1.16.0
go: downloading github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b
go: downloading github.com/ghodss/yaml v1.0.0
go: github.com/grpc-ecosystem/grpc-gateway upgrade => v1.16.0
go get github.com/grpc-ecosystem/grpc-gateway/protoc-gen-swagger
go: downloading google.golang.org/grpc v1.33.1
go: downloading golang.org/x/net v0.0.0-20200822124328-c89045814202
go: found github.com/grpc-ecosystem/grpc-gateway/protoc-gen-swagger in github.com/grpc-ecosystem/grpc-gateway v1.16.0
# Compiling...
go build -ldflags "-X github.com/snowzach/doods/conf.Executable=doods -X github.com/snowzach/doods/conf.GitVersion=v0.2.5-2-gedd6f5d-dirty" -o doods
# github.com/snowzach/doods/detector
detector/regions.go:50:13: region.Covers undefined (type *odrpc.DetectRegion has no field or method Covers)
Makefile:42: recipe for target 'doods' failed
make: *** [doods] Error 2
The command '/bin/sh -c make' returned a non-zero code: 2
Thanks!
@mloebl I think you might have deleted too many things in detector.go
Only three lines need to be commented out (e.g. see below, keep in mind that this file might have changed in the latest doods version as at the time of writing I was on 2a850c99740c30b19ba7d653751d5174f0a0253c HEAD)
package detector
import (
"context"
"sync"
// We will support these formats
_ "image/gif"
_ "image/jpeg"
_ "image/png"
_ "github.com/lmittmann/ppm"
_ "golang.org/x/image/bmp"
emptypb "github.com/golang/protobuf/ptypes/empty"
config "github.com/spf13/viper"
"go.uber.org/zap"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"github.com/snowzach/doods/conf"
"github.com/snowzach/doods/detector/dconfig"
"github.com/snowzach/doods/detector/tensorflow"
// "github.com/snowzach/doods/detector/tflite"
"github.com/snowzach/doods/odrpc"
)
// Detector is the interface to object detectors
type Detector interface {
Config() *odrpc.Detector
Detect(ctx context.Context, request *odrpc.DetectRequest) (*odrpc.DetectResponse, error)
Shutdown()
}
// Mux handles and routes requests to the configured detectors
type Mux struct {
detectors map[string]Detector
authKey string
logger *zap.SugaredLogger
}
// Create a new mux
func New() *Mux {
m := &Mux{
detectors: make(map[string]Detector),
authKey: config.GetString("doods.auth_key"),
logger: zap.S().With("package", "detector"),
}
// Get the detectors config
var detectorConfig []*dconfig.DetectorConfig
config.UnmarshalKey("doods.detectors", &detectorConfig)
// Create the detectors
for _, c := range detectorConfig {
var d Detector
var err error
m.logger.Debugw("Configuring detector", "config", c)
switch c.Type {
// case "tflite":
// d, err = tflite.New(c)
case "tensorflow":
d, err = tensorflow.New(c)
default:
m.logger.Errorw("Could not initialize detector", "name", c.Name, "type", c.Type)
continue
}
if err != nil {
m.logger.Errorf("Could not initialize detector %s: %v", c.Name, err)
continue
}
dc := d.Config()
m.logger.Infow("Configured Detector", "name", dc.Name, "type", dc.Type, "model", dc.Model, "labels", len(dc.Labels), "width", dc.Width, "height", dc.Height)
m.detectors[c.Name] = d
}
if len(m.detectors) == 0 {
m.logger.Fatalf("No detectors configured")
}
return m
}
// GetDetectors returns the configured detectors
func (m *Mux) GetDetectors(ctx context.Context, _ *emptypb.Empty) (*odrpc.GetDetectorsResponse, error) {
detectors := make([]*odrpc.Detector, 0)
for _, d := range m.detectors {
detectors = append(detectors, d.Config())
}
return &odrpc.GetDetectorsResponse{
Detectors: detectors,
}, nil
}
// Shutdown deallocates/shuts down any detectors
func (m *Mux) Shutdown() {
for _, d := range m.detectors {
d.Shutdown()
}
}
// Run a detection
func (m *Mux) Detect(ctx context.Context, request *odrpc.DetectRequest) (*odrpc.DetectResponse, error) {
if request.DetectorName == "" {
request.DetectorName = "default"
}
detector, ok := m.detectors[request.DetectorName]
if !ok {
return nil, status.Errorf(codes.NotFound, "not found")
}
return detector.Detect(ctx, request)
}
// Handle a stream of detections
func (m *Mux) DetectStream(stream odrpc.Odrpc_DetectStreamServer) error {
// Handle cancel
ctx, cancel := context.WithCancel(stream.Context())
go func() {
select {
case <-ctx.Done():
case <-conf.Stop.Chan():
cancel()
}
}()
var send sync.Mutex
var ret error
for ctx.Err() == nil {
request, err := stream.Recv()
if err != nil {
return nil
}
m.logger.Info("Stream Request")
go func(request *odrpc.DetectRequest) {
response, err := m.Detect(ctx, request)
if err != nil {
// A non-fatal error
if status.Code(err) == codes.Internal {
send.Lock()
ret = err
cancel()
send.Unlock()
return
} else {
response = &odrpc.DetectResponse{
Id: request.Id,
Error: err.Error(),
}
}
}
send.Lock()
stream.Send(response)
send.Unlock()
}(request)
}
return ret
}
@sakalauskas Thank you for the quick reply! Same error with the file from you, so may very well be a version issue, I'll try checking out that version specifically and see what happens.
That was it! 2a850c9 built fine for me, thank you! Now to start playing with it :)
@sakalauskas Hopefully last question, I got it up and running using the config.yaml:
detectors:
- name: default
type: tensorflow
modelFile: models/faster_rcnn_inception_v2_coco_2018_01_28.pb
labelFile: models/coco_labels1.txt
numThreads: 1
numConcurrent: 1
Looks like I may be running out of memory on the GPU?
2020-11-17 18:11:23.953762: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1325] Created TensorFlow device (/job:localhost/replica:0/task:0/device:GPU:0 with 48 MB memory) -> physical GPU (device: 0, name: NVIDIA Tegra X1, pci bus id: 0000:00:00.0, compute capability: 5.3)
2020-11-17 18:11:48.557262: W tensorflow/core/common_runtime/bfc_allocator.cc:419] Allocator (GPU_0_bfc) ran out of memory trying to allocate 10.12MiB (rounded to 10616832). Current allocation summary follows.
As it runs for about 25 seconds and then:
2020-11-17 18:11:48.575983: I tensorflow/core/common_runtime/bfc_allocator.cc:921] Sum Total of in-use chunks: 40.64MiB
2020-11-17 18:11:48.576005: I tensorflow/core/common_runtime/bfc_allocator.cc:923] total_region_allocated_bytes_: 50651136 memory_limit_: 50651136 available bytes: 0 curr_region_allocation_bytes_: 101302272
2020-11-17 18:11:48.576042: I tensorflow/core/common_runtime/bfc_allocator.cc:929] Stats:
Limit: 50651136
InUse: 42619648
MaxInUse: 42619648
NumAllocs: 157
MaxAllocSize: 15925248
2020-11-17 18:11:48.576107: W tensorflow/core/common_runtime/bfc_allocator.cc:424] *************************************************************************************_______________
2020-11-17 18:11:48.576192: W tensorflow/core/framework/op_kernel.cc:1628] OP_REQUIRES failed at constant_op.cc:77 : Resource exhausted: OOM when allocating tensor of shape [3,3,576,512] and type float
2020-11-17 18:11:48.576274: E tensorflow/core/common_runtime/executor.cc:642] Executor failed to create kernel. Resource exhausted: OOM when allocating tensor of shape [3,3,576,512] and type float
Is there anything in the config.yaml I can adjust for this? Thank you!
@mloebl Actually I get this error too (but I have 4GB RAM Jetson).
If the machine is loaded with other tasks and you start the docker image, it can't obtain the GPU memory. For some reason, on boot, the Tensorflow GPU device is being created correctly. So as long as the docker image is started at the startup, GPU should be created successfully - I have been running it for months with no issues:
doods | 2020-11-17 18:27:00.453029: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1325] Created TensorFlow device (/job:localhost/replica:0/task:0/device:GPU:0 with 1046 MB memory) -> physical GPU (device: 0, name: NVIDIA Tegra X1, pci bus id: 0000:00:00.0, compute capability: 5.3)
@sakalauskas Got it, this is the 2gb board, and even with gdm disabled, still getting only about 178mb free which I sounds like the issue. Checking on ram usage, doods is alone about 1gb, not counting the rest of the services running so that makes sense. Guessing even at 178mb still not enough for it as it's failing to process anything. Thanks again for the help, maybe I'll look into the Coral units as can just plug that into my HA box.
@mloebl I think you should try adding swap, it should help a bit since doods eat a lot of RAM (currently the ubuntu running doods uses 2.8G/3.87G and swap 1.9G/5.96G)
I have taken inspiration and written a C++ version of DOODS that runs natively on a Jetson Nano. Its a proof-of-concept currently, and based on this fantastic project.
Running it on a 4GB Nano
It should run on a 2GB Nano
total used free shared buff/cache available
Mem: 4057992 1665448 1748220 44128 644324 2184256
Swap: 2028992 27676 2001316
https://github.com/RichardPar/JetsonCUDA_DOODS
Regards, Richard
This is great! I managed to get DOODS up and running on my Jetson Nano using TensorFlow. I used @sakalauskas 's Docker file from the first post and the detector.go file a few posts down.
I'm running JetPack 4.3 (which comes with CUDA 10.0). I did the git pull from master: b2a1c53. Docker-compose enables a production-like object detection service for my Home Assistant server:
version: "3"
services:
doods:
image: llego/doods:jetsonnano
container_name: doods
volumes:
- /opt/doods/models:/opt/doods/models
- /opt/doods/config.yaml:/opt/doods/config.yaml
- /usr/local/cuda-10.0/targets/aarch64-linux/lib:/usr/local/cuda-10.0/lib64
- /usr/lib/aarch64-linux-gnu:/usr/lib/aarch64-linux-gnu
ports:
- 8080:8080
restart: unless-stopped
This is great! I managed to get DOODS up and running on my Jetson Nano using TensorFlow. I used @sakalauskas 's Docker file from the first post and the detector.go file a few posts down.
I'm running JetPack 4.3 (which comes with CUDA 10.0). I did the git pull from master: b2a1c53. Docker-compose enables a production-like object detection service for my Home Assistant server:
version: "3" services: doods: image: llego/doods:jetsonnano container_name: doods volumes: - /opt/doods/models:/opt/doods/models - /opt/doods/config.yaml:/opt/doods/config.yaml - /usr/local/cuda-10.0/targets/aarch64-linux/lib:/usr/local/cuda-10.0/lib64 - /usr/lib/aarch64-linux-gnu:/usr/lib/aarch64-linux-gnu ports: - 8080:8080 restart: unless-stopped
just to save us all the steps, do you mind pushing your docker image to dockerhub?
Actually I stopped using DOODS as I moved on to running Shinobi on my Jetson Nano. So I don't even have the docker image left. And probably there have been some changes in DOODS since I compiled it.
@bgulla I moved away from DOODS as well and reinstalled Ubuntu on Jetson. I found https://github.com/blakeblackshear/frigate to be quite great. Sadly there is no hardware acceleration with Jetson yet.
It took me quite some time to add support for Jetson Nano, so I thought I would share my progress. This isn't an ideal/complete solution, maybe someone could build upon this or reuse this. Using this docker image detection time decreased from ~4 seconds to ~ 1 second using the
faster_rcnn_inception_v2_coco_2018_01_28
model as the processing was offloaded to GPU.nvcr.io/nvidia/l4t-base
image so I thought I just use pre-built binaries where Bazel is needed.doods/detector/detector.go
needs to be modified and references to Tensorflow Lite should be removed/commented before building the image. Tensorflow Lite is not really needed for Jetson Nano as we can just use Tensorflow so I did not bother adding Tensorflow Lite support.Here is the Dockerfile to build the image.
To build it:
doods
repoDockerfile.jetsonnano
docker build -t MYUSERNAME/doods:jetsonnano -f Dockerfile.jetsonnano .