380 Commits

Author SHA1 Message Date
Micaela Verucchi fe2b06d607 Fix patch
Signed-off-by: Micaela Verucchi <micaelaverucchi@gmail.com>
2020-07-16 18:37:37 +02:00
tk c4aad7fe95 Patch for CUDNN 8.0.1
Signed-off-by: tk <micaelaverucchi@gmail.com>
2020-07-16 18:16:09 +02:00
Francesco Gatti b2df9fc110 Update README.md 2020-07-13 19:51:09 +02:00
Francesco Gatti b12cf0d7c2 docker 2020-07-13 19:50:00 +02:00
Micaela Verucchi 7c2155decf Add weights download link for csresnext50-panet-spp_berkeley ( fix #63 )
Signed-off-by: Micaela Verucchi <micaelaverucchi@gmail.com>
2020-07-01 11:56:46 +02:00
Francesco Gatti 04602f3952 Yolo4-tiny batched
fix #59
2020-06-30 19:37:16 +02:00
Micaela Verucchi fe2e4eae92 yolo4tiny works on tensorRT 🐬 🐬 🐬 🐬
Signed-off-by: Micaela Verucchi <micaelaverucchi@gmail.com>
2020-06-30 15:52:58 +02:00
Micaela Verucchi 61aa24c6b7 yolov4tiny works on CUDNN
Signed-off-by: Micaela Verucchi <micaelaverucchi@gmail.com>
2020-06-30 15:19:03 +02:00
Francesco Gatti 6d9beb1ec5 Merge pull request #53 from omaralvarez/master
Fix error when parsing label files with unexpected chars
2020-06-25 10:07:41 +02:00
Omar Alvarez 2817ade782 Fix parsing label files with unexpected chars 2020-06-22 13:40:15 +02:00
Francesco Gatti 1dfc69ba89 viz yolo3 preprocess 2020-06-16 13:19:30 +02:00
Francesco Gatti 07193fc343 dealloc in test.h
fix #36
2020-06-16 12:44:12 +02:00
Francesco Gatti 1b8f45703f darknet parser cpp 2020-06-16 12:41:48 +02:00
Francesco Gatti 3d3a2427c9 viz yolo3 2020-06-16 12:36:45 +02:00
Micaela Verucchi 285c77d6dd Imptove relative paths
Signed-off-by:  Micaela Verucchi <micaelaverucchi@gmail.com>
		Francesco Gatti <gattifrancesco@hotmail.it>
2020-06-15 17:15:37 +02:00
Francesco Gatti 6dff675db7 fix wrong commit 2020-06-14 13:03:48 +02:00
Francesco Gatti cbfc8ea4f2 serialize fix 2020-06-14 13:01:45 +02:00
Francesco Gatti 567dc0f75d cmake cudnn fix 2020-06-14 12:57:29 +02:00
Micaela Verucchi ab6d2d1766 Update README
Signed-off-by: Micaela Verucchi <micaela.verucchi@unimore.it>
2020-06-12 11:39:46 +02:00
Micaela Verucchi be9e327aef Fix minor, update readme
Signed-off-by: Micaela Verucchi <micaelaverucchi@gmail.com>
2020-06-09 21:01:19 +02:00
Francesco Gatti 211eff8ad0 Merge branch 'master' of https://github.com/ceccocats/tkDNN 2020-06-09 20:53:17 +02:00
Francesco Gatti 20303ac32e cudnn8 compile 2020-06-09 20:53:05 +02:00
Micaela Verucchi 3ea23815a4 Update README.md 2020-06-03 11:01:17 +02:00
Francesco Gatti 62e4a3f779 memory release 2020-06-02 12:43:06 +02:00
Francesco Gatti 0458f361b1 release layer wgs and version update 2020-06-01 21:03:37 +02:00
Francesco Gatti 2f243f26e5 readme update 2020-06-01 19:04:39 +02:00
Francesco Gatti c8ed6d782a all test ok 2020-06-01 16:15:29 +02:00
Francesco Gatti d4e0d07e09 merge 2020-06-01 15:34:59 +02:00
Micaela Verucchi 0548a662f5 Merge branch 'master' of https://github.com/ceccocats/tkDNN into eval 2020-06-01 15:18:29 +02:00
Micaela Verucchi a0e4e9f209 Modify yolov4_berkeley link for download, clean to merge with master
Signed-off-by: Micaela Verucchi <micaelaverucchi@gmail.com>
2020-06-01 15:17:53 +02:00
Francesco Gatti 18794d52c2 darknet parser tested 2020-06-01 14:55:08 +02:00
Francesco Gatti d2e2669b6d darknet parse all net to be tested 2020-06-01 12:22:55 +02:00
Micaela Verucchi d8fbee58d8 Add names files
Signed-off-by: Micaela Verucchi <micaelaverucchi@gmail.com>
2020-06-01 10:42:06 +02:00
Micaela Verucchi a6eef498fa Check
Signed-off-by: Micaela Verucchi <micaelaverucchi@gmail.com>
2020-06-01 10:39:13 +02:00
Micaela Verucchi 826fcc97c8 Read classes' names from file
Signed-off-by: Micaela Verucchi <micaelaverucchi@gmail.com>
2020-06-01 10:34:48 +02:00
Francesco Gatti 6d81473b2a yolo3 parsed ok 2020-05-30 22:11:00 +02:00
Francesco Gatti 0621ed223b Merge branch 'darknetparser' of https://github.com/ceccocats/tkDNN into darknetparser 2020-05-30 19:38:31 +02:00
Francesco Gatti 0ae96a6bc4 darknet parser to be tested on yolo3 2020-05-30 19:38:26 +02:00
Micaela Verucchi d45947eec5 Add group field
Signed-off-by: Micaela Verucchi <micaelaverucchi@gmail.com>
2020-05-30 19:03:29 +02:00
Micaela Verucchi e5e6654b1d Add fields to darknetParseFields
Signed-off-by: Micaela Verucchi <micaelaverucchi@gmail.com>
2020-05-30 18:44:17 +02:00
Francesco Gatti 298487d5c5 parse yolo layers 2020-05-30 18:44:02 +02:00
Micaela Verucchi 6b6dbabba3 Modify darknetFields_t
Signed-off-by: Micaela Verucchi <micaelaverucchi@gmail.com>
2020-05-30 18:10:14 +02:00
Francesco Gatti e1d5f58c3f layer parser 2020-05-30 18:02:20 +02:00
Micaela Verucchi 041a5cf65d Add some fields
Signed-off-by: Micaela Verucchi <micaelaverucchi@gmail.com>
2020-05-30 18:00:22 +02:00
Francesco Gatti 8935d85e91 parse layer and network 2020-05-30 17:59:00 +02:00
Micaela Verucchi 64d22c51f1 Add darknetParseFields
Signed-off-by: Micaela Verucchi <micaelaverucchi@gmail.com>
2020-05-30 17:57:48 +02:00
Micaela Verucchi eec8de3efa merge
Signed-off-by: Micaela Verucchi <micaelaverucchi@gmail.com>
2020-05-30 17:33:18 +02:00
Francesco Gatti 548a3dd33c parse line by line 2020-05-30 17:27:22 +02:00
Micaela Verucchi 15105e90d3 Add parseType
Signed-off-by: Micaela Verucchi <micaelaverucchi@gmail.com>
2020-05-30 17:25:48 +02:00
Francesco Gatti 4e1c7a70b1 darknet parser interface 2020-05-30 16:58:40 +02:00
Micaela Verucchi d936e5f740 Add mish_yashas
Signed-off-by: Micaela Verucchi <micaelaverucchi@gmail.com>
2020-05-30 16:57:53 +02:00
Francesco Gatti 90dd1d95f3 Update LICENSE 2020-05-28 14:44:07 +02:00
Micaela Verucchi 854e1d909a Fix original size
Signed-off-by: Micaela Verucchi <micaelaverucchi@gmail.com>
2020-05-19 16:33:45 +02:00
Micaela Verucchi 377310af50 Add variable batch for detector update
Signed-off-by: Micaela Verucchi <micaelaverucchi@gmail.com>
2020-05-19 09:32:27 +02:00
Micaela Verucchi 0a9e01db15 Add yolo4_berkeley test
Signed-off-by: Micaela Verucchi <micaelaverucchi@gmail.com>
2020-05-15 09:48:59 +02:00
Micaela Verucchi 23b40de508 Add verbose define
Signed-off-by: Micaela Verucchi <micaelaverucchi@gmail.com>
2020-05-15 09:41:27 +02:00
Micaela Verucchi 5d01a3f629 Fix Centernet postprocessing
Signed-off-by: Micaela Verucchi <micaelaverucchi@gmail.com>
2020-05-14 17:13:38 +02:00
Micaela Verucchi 40456592fc Adapt detection classes to use batches, adapt demos, update README
Signed-off-by: Micaela Verucchi <micaelaverucchi@gmail.com>
2020-05-14 16:41:51 +02:00
Micaela Verucchi 2e3cb52cff Add flag to disable visualization and save video
Signed-off-by: Micaela Verucchi <micaelaverucchi@gmail.com>
2020-05-11 15:08:10 +02:00
Micaela Verucchi f684a2126e Merge branch 'master' of https://github.com/ceccocats/tkDNN into eval 2020-05-11 11:58:51 +02:00
Micaela Verucchi 533bb48789 Add json detection creation for codalab check
Signed-off-by: Micaela Verucchi <micaelaverucchi@gmail.com>
2020-05-11 11:57:58 +02:00
Francesco Gatti ca7631250c filter yaw ok 2020-05-03 19:12:10 +02:00
Francesco Gatti 7f0d9a930d Merge branch 'tree' into ipmslam 2020-05-03 15:58:43 +02:00
Francesco Gatti 85bbbf42a1 merge 2020-05-03 15:58:00 +02:00
Francesco Gatti df76766890 Imu odom weights 2020-05-03 15:56:30 +02:00
Francesco Gatti 2594e491d4 Merge branch 'master' of https://github.com/ceccocats/tkDNN 2020-05-03 15:54:42 +02:00
Francesco Gatti 5a9ed44b6a SEP model 2020-05-03 15:54:39 +02:00
Francesco Gatti 9b3752d77a Merge branch 'master' of https://github.com/ceccocats/tkDNN 2020-05-03 15:53:51 +02:00
Francesco Gatti 5ab2e63de4 imu odom SEP model 2020-05-03 15:53:35 +02:00
Francesco Gatti 98537624cf merge tree 2020-05-01 15:39:00 +02:00
Micaela Verucchi 4fd84b1876 Update README.md 2020-04-29 18:34:06 +02:00
Francesco Gatti d8f034a7ad Update README.md 2020-04-29 18:17:32 +02:00
Francesco Gatti d6c28c5ba2 Update README.md 2020-04-29 18:09:50 +02:00
Francesco Gatti 3e2d0630b7 Update README.md 2020-04-29 13:07:26 +02:00
Francesco Gatti 986ec5d00c Update LICENSE 2020-04-28 22:59:45 +02:00
Micaela Verucchi adb5a693cd Modify download
Signed-off-by: Micaela Verucchi <micaelaverucchi@gmail.com>
2020-04-28 20:40:35 +02:00
Micaela Verucchi db0f8a4d99 Support yolov4
Signed-off-by: Micaela Verucchi <micaelaverucchi@gmail.com>
2020-04-28 20:35:30 +02:00
Francesco Gatti e6d435a463 Merge commit '04bd5d7ff46270c732b76cd9656e22de930e138e' into tree 2020-04-28 14:54:18 +02:00
Micaela Verucchi a874fad2bd Merge branch 'master' of https://github.com/ceccocats/tkDNN into cnet 2020-04-28 14:43:24 +02:00
Francesco Gatti 04bd5d7ff4 stream 2020-04-28 14:36:02 +02:00
Micaela Verucchi 89f91f568e Fix shortcutRT plugin, now works with batches, fix yolo3_512 downlaod link
Signed-off-by: Micaela Verucchi <micaelaverucchi@gmail.com>
2020-04-28 14:34:12 +02:00
Francesco Gatti c975a467b1 sensor close if not started fix 2020-04-28 12:59:30 +02:00
dsapienza 6e5ab031c4 Deformable batch works
Signed-off-by: Davide Sapienza <sapienza.dav@gmail.com>
2020-04-25 02:47:31 +02:00
Micaela Verucchi f418a1f9b2 Add bdd new tests, add BDD100K_val download, fix yolo3-512 link
Signed-off-by: Micaela Verucchi <micaelaverucchi@gmail.com>
2020-04-24 12:39:57 +02:00
Francesco Gatti 3ba276a236 merge tkDNN 2020-04-24 11:18:22 +02:00
Francesco Gatti 13c9dc6620 RegionRT softmax fix 2020-04-24 00:08:06 +02:00
Francesco Gatti 1ea6097a97 Reshape batch fix 2020-04-23 23:51:23 +02:00
Francesco Gatti 8cff886ee5 Flatten batch to be checked 2020-04-23 01:18:27 +02:00
Francesco Gatti 488887992c test batch 2020-04-23 00:54:03 +02:00
Francesco Gatti 8caff5f598 RouteRt is not used 2020-04-21 19:50:45 +00:00
Francesco Gatti 3d940a9fa2 batch seems ok in yolo3_berkely
layers to be checked:
DeformableConvRT
FlattenConcatRT
ReshapeRT
RouteRT (dont know why but seems working)
2020-04-21 19:41:40 +00:00
Francesco Gatti 7c81c5a43c batch size > 1 2020-04-21 19:20:44 +02:00
Francesco Gatti b1818b81d9 Merge pull request #2 from ceccocats/cnet
Move download of weights inside build folder
2020-04-18 12:43:23 +02:00
Micaela Verucchi 2fbac7705d Move download of weights inside build folder
Signed-off-by: Micaela Verucchi <micaelaverucchi@gmail.com>
2020-04-17 22:36:25 +02:00
Francesco Gatti cbea75a8f6 merge master 2020-04-15 14:21:33 +02:00
Francesco Gatti 4a308467e6 warning fix 2020-04-14 14:26:06 +02:00
Francesco Gatti 29b99f4e61 pull from repos 2020-04-14 12:32:50 +02:00
Francesco Gatti e3e5a133f5 pull from repos 2020-04-12 21:47:25 +02:00
Francesco Gatti f637aa0ea8 Create LICENSE 2020-04-09 22:13:50 +02:00
Francesco Gatti c654610569 readme update 2020-04-09 20:15:37 +02:00
Francesco Gatti 85588f7343 warning fix 2020-04-09 20:05:10 +02:00
Francesco Gatti f9e3f17c0a cmake dont download test data 2020-04-09 20:00:29 +02:00
Francesco Gatti cb5b7a1d98 ignore calib table 2020-04-09 19:56:08 +02:00
Davide Sapienza 106cbb5c73 Remove the optional parameters from the Pooling layer.
Signed-off-by: Davide Sapienza <sapienza.dav@gmail.com>
2020-04-09 19:20:27 +02:00
Micaela Verucchi fabad7bace Add mnist download, change ERROR_TKDNN into ERROR_TENSORRT
Signed-off-by: Micaela Verucchi <micaelaverucchi@gmail.com>
2020-04-09 19:02:25 +02:00
Davide Sapienza 4361d5fec0 Remove the final parameter from the layers
Signed-off-by: Davide Sapienza <sapienza.dav@gmail.com>
2020-04-09 18:48:03 +02:00
Micaela Verucchi 3502c5b676 Fix pooling, add return code in each test, add return code handling in test_all_tests script
Signed-off-by: Micaela Verucchi <micaelaverucchi@gmail.com>
2020-04-09 15:25:05 +02:00
Francesco Gatti ed0596a52c warning fix 2020-04-09 01:00:14 +02:00
Francesco Gatti 2635d24855 Merge branch 'master' into cnet 2020-04-09 00:57:43 +02:00
Francesco Gatti 1bb9f73a0b remove deprecated and unused warning 2020-04-09 00:55:07 +02:00
Francesco Gatti c1247930c9 gnuplot imuodom 2020-04-08 16:53:35 +02:00
Micaela Verucchi bddb0110ca Add imuodom download and test in script
Signed-off-by: Micaela Verucchi <micaelaverucchi@gmail.com>
2020-04-08 16:50:40 +02:00
Micaela Verucchi 6d1fda0c21 Compile on tx2
Signed-off-by: Micaela Verucchi <micaelaverucchi@gmail.com>
2020-04-08 16:23:08 +02:00
Micaela Verucchi 35e86ca5cb Improve test_all_tests scripts to run in every mode (FP32, FP16, INT8)
Signed-off-by: Micaela Verucchi <micaelaverucchi@gmail.com>
               Davide Sapienza <sapienza.dav@gmail.com>
2020-04-08 15:29:49 +02:00
Micaela Verucchi 0debd01ba7 Minor, uncomment test_all_tests
Signed-off-by: Micaela Verucchi <micaelaverucchi@gmail.com>
2020-04-08 15:05:52 +02:00
Micaela Verucchi 0951f4644f Merge with master works
Signed-off-by:  Micaela Verucchi <micaelaverucchi@gmail.com>
		Davide Sapienza <sapienza.dav@gmail.com>
2020-04-08 14:59:42 +02:00
Micaela Verucchi 6ec417d89f Add scripts folder
Signed-off-by: Micaela Verucchi <micaelaverucchi@gmail.com>
2020-04-08 14:24:34 +02:00
Micaela Verucchi ba04328d48 Ok test script, output removed
Signed-off-by: Micaela Verucchi <micaelaverucchi@gmail.com>
2020-04-08 14:06:30 +02:00
Micaela Verucchi ef78d7f176 Add BoundingBox class
Signed-off-by: Micaela Verucchi <micaelaverucchi@gmail.com>
2020-04-08 13:52:29 +02:00
Micaela Verucchi f089d59d10 Add script to check if every test works fine
Signed-off-by: Micaela Verucchi <micaelaverucchi@gmail.com>
2020-04-08 13:49:06 +02:00
Micaela Verucchi da79128271 Update download url
Signed-off-by: Micaela Verucchi <micaelaverucchi@gmail.com>
2020-04-08 12:34:02 +02:00
Micaela Verucchi 5f6011b206 Merge branch 'cnet' of https://github.com/ceccocats/tkDNN into cnet 2020-04-08 11:20:56 +02:00
Micaela Verucchi ae1d8cd9e6 Refactoring & documentation
Signed-off-by: Micaela Verucchi <micaelaverucchi@gmail.com>
2020-04-08 11:20:48 +02:00
Davide Sapienza 0e5c90634f Fix the Deformable convolution code sintax.
Signed-off-by: Davide Sapienza <sapienza.dav@gmail.com>
2020-04-08 11:14:34 +02:00
Davide Sapienza 5562f599a6 Fix the INT8 calibrator sintax
Signed-off-by: Davide Sapienza <sapienza.dav@gmail.com>
2020-04-08 10:22:03 +02:00
Micaela Verucchi 326c7e0940 Move extraction of name into function in utils
Signed-off-by: Micaela Verucchi <micaelaverucchi@gmail.com>
2020-04-08 10:09:15 +02:00
Micaela Verucchi c36befaf2b Minor fix on output file name in map demo
Signed-off-by: Micaela Verucchi <micaelaverucchi@gmail.com>
2020-04-08 09:35:54 +02:00
Davide Sapienza cf3fbeddbd Fix the sorting kernels used in the CenterNet pre and post-processing.
This commit moves the kernels in the correct sub-directory.
It creates new header file for Thrust kernels. It splits the
kernels into two files: 'normalize.cu' contains CenterNet
pre-processing operations, 'postprocessing.cu' contains the
CenterNet post-processing operations.

Signed-off-by: Davide Sapienza <sapienza.dav@gmail.com>
2020-04-07 18:28:12 +02:00
Davide Sapienza ae876e22ee Update README.md for INT8 inference
Signed-off-by: Davide Sapienza <sapienza.dav@gmail.com>
2020-04-06 20:27:59 +02:00
Davide Sapienza 26dcb7b8c9 Fix the tensorRT code to support versions prior to 6.0
Signed-off-by: Davide Sapienza <sapienza.dav@gmail.com>
2020-04-06 19:54:40 +02:00
Micaela Verucchi 455291b6dd Fix compile errors dut to Int8BatchStream
Signed-off-by: Micaela Verucchi <micaela.verucchi@unimore.it>
               Davide Sapienza <sapienza.dav@gmail.com>
2020-04-06 19:11:39 +02:00
Micaela Verucchi 8575059666 Add again evalutation.h
Signed-off-by: Micaela Verucchi <micaelaverucchi@gmail.com>
2020-04-06 18:35:52 +02:00
Micaela Verucchi 9ec0913d7f Merge branch 'cnet' of https://github.com/ceccocats/tkDNN into cnet 2020-04-06 18:13:02 +02:00
Micaela Verucchi c8308963df Add evaluation to tk::dnn namespace, style fix also
Signed-off-by: Micaela Verucchi <micaelaverucchi@gmail.com>
2020-04-06 18:12:38 +02:00
Davide Sapienza e3442e4764 Move the calibration table saving to the tests/network folder.
Signed-off-by: Davide Sapienza <sapienza.dav@gmail.com>
2020-04-06 18:06:21 +02:00
Micaela Verucchi c0a978a480 Add opencv install script (for real)
Signed-off-by: Micaela Verucchi <micaela.verucchi@unimore.it>
2020-04-06 17:27:25 +02:00
Micaela Verucchi 674c61d280 Add opencv script, modified macro, add opencv section into readme
Signed-off-by: Micaela Verucchi <micaela.verucchi@unimore.it>
2020-04-06 17:25:53 +02:00
Micaela Verucchi dfdeb8b36e Modify weights download for some nets, now also calibration tables are downloaded in tests folder
Signed-off-by: Micaela Verucchi <micaelaverucchi@gmail.com>
2020-04-06 16:22:23 +02:00
Davide Sapienza e4900120db Fix getNetworkRTName (works also on Xavier)
Signed-off-by: Davide Sapienza <sapienza.dav@gmail.com>
2020-04-02 10:15:30 +02:00
Micaela Verucchi 79a05a8159 Modify weights download link for mobilenetv2ssd512 and yolo3_tiny512
Signed-off-by: Micaela Verucchi <micaelaverucchi@gmail.com>
2020-04-02 09:41:24 +02:00
Micaela Verucchi af13e7c954 Add getMemoryUsage function, detection update moved in abstract lass, splitted execution time in pre-inf-post, other minors.
Signed-off-by: Micaela Verucchi <micaelaverucchi@gmail.com>
2020-04-01 19:18:43 +02:00
Davide Sapienza c06c9fcf23 Update README.md
Signed-off-by: Davide Sapienza <sapienza.dav@gmail.com>
2020-03-30 19:02:55 +02:00
Davide Sapienza bb157be82c Add TKDNN_CALIB_IMG_PATH and TKDNN_CALIB_LABRL_PATH variable
This commit adds two variables for the calibration dataset.
The first is reffered to .txt file that contains the list
of the absolute paths of the images for the INT8 calitration.
The second is referred to .txt file that contains the list
of the absolute paths of the labels of the same images above.

Signed-off-by: Davide Sapienza <sapienza.dav@gmail.com>
2020-03-30 18:55:32 +02:00
Davide Sapienza ce20868bad Add TKDNN_MODE variable to the name of the network.
This commit permits to obtain different .rt files for different
precision optimizations of the same network.

Signed-off-by: Davide Sapienza <sapienza.dav@gmail.com>
2020-03-30 15:08:25 +02:00
Micaela Verucchi 573924cf2c Update README.md 2020-03-29 20:15:15 +02:00
Micaela Verucchi f2a4125d9f Update README.md 2020-03-29 20:07:27 +02:00
Micaela Verucchi d7276c720d Update README.md 2020-03-29 20:03:59 +02:00
Davide Sapienza 482e122655 Fix opencv cuda include error
Signed-off-by: Davide Sapienza <sapienza.dav@gmail.com>
2020-03-27 10:43:49 +01:00
Davide Sapienza 08e1801c60 Add the Int8 calibrator and the tensorRT Int8 inference
Signed-off-by: Davide Sapienza <sapienza.dav@gmail.com>
2020-03-27 00:48:14 +01:00
Micaela Verucchi 7c55dcb708 Add tp tests for yolo3512 and yolo3tiny512
Signed-off-by: Micaela Verucchi <micaelaverucchi@gmail.com>
2020-03-26 15:06:49 +01:00
Micaela Verucchi 3eda9b9219 Add GPU version for yolo3detection
Signed-off-by: Micaela Verucchi <micaelaverucchi@gmail.com>
2020-03-23 21:29:29 +01:00
Micaela Verucchi df37e11709 Modify map demo, using abstract class. Move draw function in abstract class
Signed-off-by: Micaela Verucchi <micaelaverucchi@gmail.com>
2020-03-23 19:32:37 +01:00
Micaela Verucchi bbcc33c0cf Refactoring for detection NN
Signed-off-by: Micaela Verucchi <micaelaverucchi@gmail.com>
2020-03-20 21:14:12 +01:00
Micaela Verucchi c7d9c38ea0 Add OPENCV_CUDA define, to allow having preprocess both in CPU and GPU (Mobilenet and Centernet)
Signed-off-by: Micaela Verucchi <micaelaverucchi@gmail.com>
2020-03-20 10:21:11 +01:00
Micaela Verucchi 58fe723b6a Style fix, useless params removed
Signed-off-by: Micaela Verucchi <micaelaverucchi@gmail.com>
2020-03-19 18:13:35 +01:00
Micaela Verucchi f44f377771 Add preprocess function, allow preprocess on GPU for mobilenetdetection
Signed-off-by: Micaela Verucchi <micaelaverucchi@gmail.com>
2020-03-19 17:53:29 +01:00
Micaela Verucchi 41b1135fb3 Add support for mobilenet in map_demo
Signed-off-by: Micaela Verucchi <micaelaverucchi@gmail.com>
2020-03-17 15:08:43 +01:00
Micaela Verucchi 43fd92f701 Fix conv2d with additional bias for tensorRT. Fix reshape deserialize. Mb2512 works with tensorRT
Signed-off-by: Micaela Verucchi <micaelaverucchi@gmail.com>
2020-03-17 13:18:05 +01:00
Micaela Verucchi 1d388ca51a Add mobilenetv2ssdlite512 test.
Works for CuDNN, not for tensorRT.
Modified channels in second convolution for classification headers from 126 to 486, when changing size from 300 to 512.
Added size 512 SSD specs and support to COCO dataset (81 classes, first BACKGROUND due to repo for training).
Refactoring class names.

Signed-off-by: Micaela Verucchi <micaelaverucchi@gmail.com>
2020-03-17 10:35:02 +01:00
Micaela Verucchi 9c25d15ff2 Add yolov3_512 (size 512) test 2020-03-16 11:29:15 +01:00
Francesco Gatti 62c8f528a4 eigen assert fix 2020-03-14 19:50:55 +01:00
Micaela Verucchi 82d907971c Fix download weights yolov3 versions
Signed-off-by: Micaela Verucchi <micaela.verucchi@unimore.it>
2020-03-14 18:20:32 +01:00
Francesco Gatti 555b32b5dc Refactoring
Signed-off-by: Francesco Gatti <gattifrancesco@hotmail.it>
2020-03-14 17:22:58 +01:00
Francesco Gatti cf7fbadcd2 Add function to download weigths if do no exist, for each test. Add some controls in map demo.
Signed-off-by: Francesco Gatti <gattifrancesco@hotmail.it>
2020-03-14 17:02:07 +01:00
xavier 5e0c1879bc Merge branch 'cnet' of https://github.com/ceccocats/tkDNN into cnet 2020-03-13 12:17:21 +01:00
xavier 32dd807ab0 Add Yolov3_tiny512 test cpp
Signed-off-by: xavier <micaelaverucchi@gmail.com>
2020-03-13 12:16:18 +01:00
Micaela Verucchi 8aa792925d Update README.md 2020-03-12 20:42:44 +01:00
xavier 9d17cb42f4 Merge branch 'cnet' of https://github.com/ceccocats/tkDNN into cnet 2020-03-12 20:18:11 +01:00
xavier db10ebeb34 Fix print on times.csv
Signed-off-by: xavier <micaelaverucchi@gmail.com>
2020-03-12 20:18:02 +01:00
Francesco Gatti 62e7882744 Merge branch 'cnet' of https://github.com/ceccocats/tkDNN into cnet 2020-03-12 18:43:33 +01:00
Francesco Gatti 13b4dffd71 csresnext50-panet-spp works with TensorRT
Signed-off-by: Francesco Gatti <gattifrancesco@hotmail.it>
2020-03-12 18:24:41 +01:00
Francesco Gatti f6527f51e3 Add csresnext50-panet-spp test. Works on CUDNN. Does not work with TensorRT
Signed-off-by: Francesco Gatti <gattifrancesco@hotmail.it>
2020-03-11 18:37:26 +01:00
Micaela Verucchi 66e3b98b04 Update README.md 2020-03-11 12:04:28 +01:00
Micaela Verucchi 0cc2666e26 Update README.md 2020-03-11 11:51:28 +01:00
xavier d0d462c015 Merge
Signed-off-by: xavier <micaelaverucchi@gmail.com>
2020-03-10 15:43:26 +01:00
xavier 2d46f16b70 Add tiny yolo 512 test
Signed-off-by: xavier <micaelaverucchi@gmail.com>
2020-03-10 15:40:11 +01:00
Micaela Verucchi e6aa73d7bc Update README.md 2020-03-10 15:26:57 +01:00
Micaela Verucchi 4b85a2238a Add writing results on file for map demo
Signed-off-by: Micaela Verucchi <micaelaverucchi@gmail.com>
2020-03-10 14:35:25 +01:00
Francesco Gatti 8944778dcf imuodom fix 2020-03-09 22:05:34 +01:00
Francesco Gatti 406f8cc9b3 - ImuOdom model into class
- Route layer input array hard copy
- fix utils
2020-03-09 19:44:21 +01:00
Micaela Verucchi 7ea31d123a Update README
Signed-off-by: Micaela Verucchi <micaela.verucchi@unimore.it>
2020-03-08 18:12:08 +01:00
Davide Sapienza 7dbbbe4d9a Update README
Signed-off-by: Davide Sapienza <sapienza.dav@gmail.com>
2020-03-03 17:34:01 +01:00
Davide Sapienza 01a42ffe27 Move multiple demo files into one
Signed-off-by: Davide Sapienza <sapienza.dav@gmail.com>
2020-03-03 17:30:35 +01:00
Davide Sapienza 296a6cbc87 Add draw method to Yolo3Detection class.
Update yolo demo

Signed-off-by: Davide Sapienza <sapienza.dav@gmail.com>
2020-03-03 17:08:25 +01:00
Micaela Verucchi fe206ea24c Fix dependencies problems
Signed-off-by: Micaela Verucchi <micaelaverucchi@gmail.com>
2020-02-27 16:48:10 +01:00
xavier 3eb079dd13 Add Mobilenetv2 SSD Lite post and preprocessing, add mobilenet demo
Signed-off-by: xavier <micaelaverucchi@gmail.com>
2020-02-26 17:42:20 +01:00
xavier 110bf56dc4 Fix include error
Signed-off-by: xavier <micaelaverucchi@gmail.com>
2020-02-21 11:14:52 +01:00
xavier 209a3e8492 Merge branch 'cnet' of https://github.com/ceccocats/tkDNN into cnet 2020-02-21 10:49:35 +01:00
xavier 38a1b9dcb2 Add Mobilenet2SSDLite test
The new test works both with TensorRT and cuDNN. Preprocessing and
Postprocessing are missing. Add ClippedReLU (for ReLU6), groups for
Conv2d, additional bias for convolution.

Other minors:
-move the timer in the detector to measure all the
processing time for a given frame (both centernet and yolo);
-add int8 flag.

Signed-off-by: Micaela Verucchi <micaelaverucchi@gmail.com>
Davide Sapienza <sapienza.dav@gmail.com>
2020-02-21 10:45:46 +01:00
Francesco Gatti 443691414a LSTM ok 2020-02-16 17:21:58 +01:00
Francesco Gatti 1a1c54f364 structure ok, result wrong 2020-02-16 17:08:19 +01:00
Francesco Gatti 10b7160677 works but it need cleaning 2020-02-16 16:28:39 +01:00
Francesco Gatti 4746121d43 LSTM params 2020-02-15 20:37:08 +01:00
Davide Sapienza 2c1df5619f Move pre-processing on GPU
Signed-off-by: Davide Sapienza <sapienza.dav@gmail.com>
2020-02-14 18:44:13 +01:00
Francesco Gatti 4fa5d2c231 lstm return seq 2020-02-13 23:21:28 +01:00
Francesco Gatti c1c2173e4d removed unused var 2020-02-13 23:10:48 +01:00
Francesco Gatti 03d39d991c LSTM to be tested 2020-02-13 23:04:29 +01:00
Francesco Gatti a9c0db0bf6 LSTM cudnn test 2020-02-13 19:27:18 +01:00
Davide Sapienza 97b88ef52d Fix a bug in the deformable kernel.
There was a wrong variable initialization.

Fixes: 51ffcb1f50 ("Optimize deformable kernel")

Signed-off-by: Davide Sapienza <sapienza.dav@gmail.com>
2020-02-11 16:28:17 +01:00
Micaela Verucchi 4c2d2a7965 Update README.md 2020-02-11 15:12:27 +01:00
xavier 636d899f9f Merge README
Signed-off-by: xavier <micaelaverucchi@gmail.com>
2020-02-11 14:58:25 +01:00
xavier 7e21b10aee Add script to download COCO val2017
Signed-off-by: xavier <micaelaverucchi@gmail.com>
2020-02-11 14:56:54 +01:00
Micaela Verucchi 6e2ff405f4 Update README.md 2020-02-11 11:28:20 +01:00
xavier 1936e54870 Change README.md, add config.yaml, refactoring
Signed-off-by: xavier <micaelaverucchi@gmail.com>
2020-02-11 11:25:42 +01:00
xavier b5c0baa99d Merge branch 'cnet' of https://github.com/ceccocats/tkDNN into cnet 2020-02-11 10:32:52 +01:00
xavier 801b8b5641 Read parameters for mAP from yaml, add yampl-cpp dependency
Signed-off-by: xavier <micaelaverucchi@gmail.com>
2020-02-11 10:32:42 +01:00
Davide Sapienza 51ffcb1f50 Optimize deformable kernel
Signed-off.by: Ignacio Sañudo Olmedo<ignacio.sanudoolmedo@unimore.it>
Signed-off-by: Davide Sapienza <sapienza.dav@gmail.com>
2020-02-11 10:06:08 +01:00
xavier 10831ab450 Merge branch 'cnet' of https://github.com/ceccocats/tkDNN into cnet 2020-02-10 18:19:12 +01:00
xavier d601e980f6 Add avg precision, recall, f1score computation, other minors
Signed-off-by: xavier <micaelaverucchi@gmail.com>
2020-02-10 18:19:08 +01:00
Davide Sapienza b06dc286e9 Update README.md
Signed-off-by: Davide Sapienza <sapienza.dav@gmail.com>
2020-02-10 11:19:39 +01:00
Davide Sapienza c02238ddc8 Add Anaconda environment for ResNet101 and DLA34 weights exporter
Signed-off-by: Davide Sapienza <sapienza.dav@gmail.com>
2020-02-10 10:58:04 +01:00
Davide Sapienza e72aa348a0 Add DLA34 weights exporter
Signed-off-by: Davide Sapienza <sapienza.dav@gmail.com>
2020-02-10 10:56:33 +01:00
Davide Sapienza 62fe82ce9e Update ResNet101 weights exporter
Signed-off-by: Davide Sapienza <sapienza.dav@gmail.com>
2020-02-10 10:54:04 +01:00
Davide Sapienza 9007e25a00 Remove mallocs and frees from the kernels
Signed-off-by: Davide Sapienza <sapienza.dav@gmail.com>
2020-02-07 14:50:05 +01:00
xavier 289a97d06c Refactoring map_demo, add evaluation.h and evaluation.cpp
Signed-off-by: xavier <micaelaverucchi@gmail.com>
2020-02-07 12:47:02 +01:00
xavier f32d8a859b Add mAP 0.5:0.95, other small fix
Signed-off-by: xavier <micaelaverucchi@gmail.com>
2020-02-07 09:09:40 +01:00
xavier 5c501f529b Merge branch 'cnet' of https://github.com/ceccocats/tkDNN into cnet 2020-02-07 09:06:29 +01:00
Davide Sapienza 2503eba173 Fix memory leak
This commit moves cublasCreate out from dcn_v2_cuda_forward
to save some milliseconds and it adds cublasDestroy (cause
of memory leak).

Signed-off-by: Davide Sapienza <sapienza.dav@gmail.com>
2020-02-06 23:09:12 +01:00
xavier c21a0687ce Merge branch 'cnet' of https://github.com/ceccocats/tkDNN into cnet 2020-02-06 18:24:49 +01:00
Davide Sapienza 70eb5214cc Change CenterNet input dimension.
This commit changes the image input dimension, it updates the
CenterNet detection class.

Signed-off-by: Davide Sapienza <sapienza.dav@gmail.com>
2020-02-06 18:08:06 +01:00
xavier 37019597af Merge branch 'cnet' of https://github.com/ceccocats/tkDNN into cnet 2020-02-05 18:39:32 +01:00
xavier d8eeb36d4b Add mAP computation and demo
Signed-off-by: xavier <micaelaverucchi@gmail.com>
2020-02-05 18:39:13 +01:00
Davide Sapienza c695d8c5d7 Implement CenterNet based on DLA34, CUDNN and TensorRT work.
Signed-off-by: Davide Sapienza <sapienza.dav@gmail.com>
2020-02-05 14:59:56 +01:00
Davide Sapienza 4616be0738 Add grouped convolutions in CUDNN and tensorRT.
Signed-off-by: Davide Sapienza <sapienza.dav@gmail.com>
2020-02-05 14:32:58 +01:00
Davide Sapienza fe85c26888 Implement DLA34, CUDNN and TensorRT work.
Signed-off-by: Davide Sapienza <sapienza.dav@gmail.com>
2020-01-24 19:30:32 +01:00
Davide Sapienza 7f239efdc0 Centernet: fix pooling problem, add centrnet demo
Signed-off-by: Micaela Verucchi <micaelaverucchi@gmail.com>
Signed-off-by: Davide Sapienza <sapienza.dav@gmail.com>
2020-01-21 12:50:18 +01:00
Davide Sapienza c68d6f318e Merge branch 'master' of https://github.com/ceccocats/tkDNN into cnet 2020-01-20 16:41:19 +01:00
luca 8a4d1cac17 compile with tensorrt 5 2020-01-20 14:51:38 +01:00
Davide Sapienza b23cf9fe70 Merge branch 'cnet' of https://github.com/ceccocats/tkDNN into cnet
Signed-off-by: Michaela Verucchi <micaelaverucchi@gmail.com>
Signed-off-by: Davide Sapienza <sapienza.dav@gmail.com>
2020-01-20 12:35:27 +01:00
Davide Sapienza 7838cb4922 Pre-process, Process and Post-process work
Signed-off-by: Micaela Verucchi <micaelaverucchi@gmail.com>
Signed-off-by: Davide Sapienza <sapienza.dav@gmail.com>
2020-01-20 12:27:49 +01:00
Francesco Gatti 146e144249 Update README.md 2020-01-16 18:24:35 +01:00
Francesco Gatti 2f57ba1222 Update README.md 2020-01-16 18:21:34 +01:00
xavier da4f246157 add DLA, plugin for shortcut and leaky. new verison 0.4 2020-01-15 21:48:18 +01:00
xavier 0f0c8c28e1 Merge with master, works with Jetpack 4.3
Signed-off-by: xavier <micaelaverucchi@gmail.com>
2020-01-15 19:24:19 +01:00
Francesco Gatti f3f5daf3db Merge branch 'master' of https://github.com/ceccocats/tkDNN 2020-01-15 18:07:44 +01:00
Francesco Gatti c2d73623e5 support clion 2020-01-15 18:07:40 +01:00
xavier c32a0be257 Batchnorm eps fix, works on jetpack 4.3 2020-01-15 18:06:02 +01:00
xavier 57d7743f7e Change opencv funcion call (due to OpenCV 4)
Signed-off-by: xavier <micaelaverucchi@gmail.com>
2020-01-15 09:55:10 +01:00
fbagni 23a1365dc4 Merge branch 'cnet' of https://github.com/ceccocats/tkDNN into cnet 2019-12-23 16:14:24 +01:00
fbagni 7e7f480e2b Yolov3_tiny works on tensorRT
Signed-off-by: fbagni <gattinomicino>
2019-12-23 16:11:41 +01:00
Davide Sapienza 5272f1cde6 CenterNet TensorRT serialization works
This commit adds the Deformable layer serialization.

Signed-oof-by: Davide Sapienza <sapienza.dav@gmail.com>
2019-12-23 15:31:13 +01:00
nvidia f0ea2c027f Merge branch 'cnet' of https://github.com/ceccocats/tkDNN into cnet 2019-12-20 15:27:55 +01:00
nvidia 854a4c316a Add ResizeLayerRT plugin
Signed-off-by: nvidia <micaelaverucchi@gmail.com>
2019-12-20 15:27:41 +01:00
Davide Sapienza d889ed385d CenterNet TensorRT works. TensorRT serialization not yet implemented
Signed-oof-by: Davide Sapienza <sapienza.dav@gmail.com>
2019-12-20 11:05:03 +01:00
Davide Sapienza e99b353d8b Fix the inference operation of the deformable convolutional layer.
This commit removes the malloc operation in the inference
method and adds the sigmoid kernel.

Signed-off-by: Davide Sapienza <sapienza.dav@gmail.com>
2019-12-19 14:47:57 +01:00
Davide Sapienza df888a3457 Add CenterNet based on Resnet101, TensorRT not implemented.
Signed-off-by: Davide Sapienza <sapienza.dav@gmail.com>
2019-12-18 18:59:54 +01:00
mbosi 6bf9179acc fix to drivework global path 2019-12-12 12:30:24 +01:00
Micaela Verucchi 44b2bce3ff Yolo3_tiny CUDNN works, TensorRT doesn't. Add n_masks to Yolo layer.
Signed-off-by: Micaela Verucchi <micaelaverucchi@gmail.com>
2019-12-05 20:43:48 +00:00
Micaela Verucchi a2db98670a Add Yolov3 (COCO80) and Yolov3-tiny (COCO80), TensorRT for tiny not working
Signed-off-by: Micaela Verucchi <micaelaverucchi@gmail.com>
2019-12-04 17:01:40 +00:00
Francesco Gatti b218b18a02 readme update 2019-12-02 20:24:12 +01:00
Francesco Gatti aa5927d8a1 findCUDNN 2019-11-06 14:04:23 +01:00
Francesco Gatti 2594f59d0d conv2d ok, but deconv ha different dim with tensorrt 2019-10-30 16:45:46 +01:00
Francesco Gatti f247300469 test simple 2019-10-30 15:40:48 +01:00
Micaela Verucchi 6a1707f65e Merge branch 'cnet' of https://github.com/ceccocats/tkDNN into cnet 2019-10-30 10:20:44 +01:00
Micaela Verucchi 8b64d1876f deformable conv cu 2019-10-30 10:20:04 +01:00
fbagni d6d93a74f8 fix 2019-10-30 09:42:54 +01:00
fbagni 33f36ab204 Deconv tensorrt 2019-10-30 09:40:29 +01:00
Francesco Gatti f9afee2f3b deconv layer cudnn 2019-10-30 00:05:22 +01:00
Davide Sapienza 02936fa928 ResNet working 2019-10-29 17:21:31 +01:00
Davide Sapienza e9ec582223 Shortcat ok 2019-10-29 15:08:44 +01:00
Micaela Verucchi 058f9b795f resnet weight export fix 2019-10-28 19:20:02 +01:00
Micaela Verucchi 4ac2c87d1c cmake fix 2019-10-28 18:39:28 +01:00
Micaela Verucchi 42a1ea02b9 resnet merge 2019-10-28 18:38:23 +01:00
mbosi 92f3d1c548 fixed install cmake 2019-10-01 18:47:31 +02:00
Francesco Gatti bbc4dda635 removed buildtype 2019-09-17 17:16:46 +02:00
Francesco Gatti de8b02fe50 install fix 2019-09-17 16:12:59 +02:00
Francesco Gatti ca62784f57 include dir fix, cmake dir 2019-09-17 15:22:39 +02:00
Francesco Gatti ec02c7292f save layer names in rt file 2019-09-16 19:41:59 +02:00
Francesco Gatti 77f031c0f4 save video result 2019-09-16 10:35:29 +02:00
mbosi a038e966d9 yolo3 flir ok 2019-09-15 16:19:30 +02:00
mbosi 8c629ebe7b string input and flir test 2019-09-14 19:03:13 +02:00
Francesco Gatti 041968f38a cmake fix 2019-06-29 11:08:30 +02:00
Francesco Gatti f50aa4ad1a fix cmake 2019-06-28 18:51:01 +02:00
Francesco Gatti 6656c3d0e8 fix cmake 2019-06-28 17:44:32 +02:00
Autochaffeur 4ebbb6af2b README update 2019-05-13 17:32:18 +02:00
mbosi eef1fd321f added label to demo bounding box visualization 2019-05-02 14:30:50 +02:00
Francesco Gatti a85367fa22 dla commented 2019-03-07 17:40:24 +01:00
Roberto Cavicchioli 3714155809 dla 2019-03-06 16:40:12 +01:00
Francesco Gatti c22219ad16 DLA number print 2019-03-06 13:02:39 +01:00
Francesco Gatti 7505c28d2d include fix 2019-02-19 11:09:27 +00:00
rcavicchioli 39f80bbfb6 coco4 2019-02-19 11:38:13 +01:00
rcavicchioli 851c6a366c arg fix 2019-02-19 11:10:34 +01:00
Francesco Gatti de04ae1cab doc 2019-02-19 09:03:33 +00:00
Francesco Gatti 1aa4f0275d color fix 2019-02-19 08:57:51 +00:00
Francesco Gatti c7941666ec demo for more yolo3 2019-02-19 08:43:35 +00:00
Francesco Gatti 87fe342ca2 yoloRT load anchors 2019-02-18 21:39:14 +01:00
Francesco Gatti bdd8e0bc26 yolo3plug fix 2019-02-18 18:55:48 +00:00
Francesco Gatti 738fa94150 version update 2019-02-18 15:54:22 +00:00
Francesco Gatti 13063b904d yolo3 ok 2019-02-18 15:51:57 +00:00
Francesco Gatti 0d682136de yolo3 berkeley ok 2019-02-18 15:37:39 +00:00
Francesco Gatti 2c63bf05be multipl yolo morge 2019-02-06 22:24:01 +00:00
Francesco Gatti 0e97452460 dects dont works 2019-02-05 20:09:47 +00:00
Francesco Gatti c8dea4668d compute detections 2019-02-04 20:34:15 +00:00
Francesco Gatti 88097a3774 yolo3 ok 2019-01-04 22:28:10 +01:00
Francesco Gatti 2e8d0b1002 yolo3 86 route error 2018-12-23 16:20:17 +01:00
Francesco Gatti 3bd725801d upsample ok, route have problems 2018-12-22 23:56:01 +01:00
Francesco Gatti 34be4cd00f yoloRT layer 2018-12-22 21:26:50 +01:00
Francesco Gatti 3b60de00f8 2 input shortcut 2018-12-21 16:17:48 +01:00
Francesco Gatti 53b429551d 2 input shortcut 2018-12-21 16:16:38 +01:00
Francesco Gatti 64626bf547 shortcut rt test 2018-12-21 15:53:39 +01:00
Francesco Gatti 7a51b4382d yolo3 ok 2018-12-21 15:28:47 +01:00
Francesco Gatti c13bda3863 yolo layer break everything 2018-12-21 11:07:35 +01:00
Francesco Gatti 2606820300 layer 96 dont match 2018-12-20 18:17:40 +01:00
Francesco Gatti a41b22e1f2 layer 94 2018-12-20 17:35:49 +01:00
Francesco Gatti c8f2e1b448 upsample ok 2018-12-20 17:08:31 +01:00
Francesco Gatti 2ab47b5874 yolo layer 2018-12-20 16:10:01 +01:00
Francesco Gatti 67cc566a0d layer 81 2018-12-20 14:52:22 +01:00
Francesco Gatti 217ff20058 layer 61 2018-12-20 12:02:47 +01:00
Francesco Gatti 991abdb410 layer 36 2018-12-20 11:46:58 +01:00
Francesco Gatti 7a46601306 yolo3 layer 15 2018-12-20 11:36:10 +01:00
Francesco Gatti e91db28756 shortcut cu 2018-12-20 09:53:17 +01:00
Francesco Gatti ed02930464 upsample template 2018-12-19 22:45:43 +01:00
Francesco Gatti 5f25e0b5f6 shortcut template 2018-12-19 22:36:46 +01:00
Francesco Gatti bc0ea65766 yolo3 debug start 2018-12-19 19:39:31 +01:00
Francesco Gatti dc55874f14 yolo cfg 2018-12-18 18:21:56 +01:00
Francesco Gatti 70373d638b fix 2018-12-18 18:09:18 +01:00
Francesco Gatti a9970f43fb tests/yolo_berkeley/yolo_berkeley.cpp 2018-12-18 18:07:37 +01:00
Francesco Gatti 6eb63160c8 berkeley 2018-12-18 14:52:18 +01:00
Francesco Gatti 6249956469 namespace change 2018-12-14 21:55:16 +01:00
Francesco Gatti 443179359d config 2018-12-03 22:04:04 +01:00
Francesco Gatti a13bc2f007 ../CMakeLists.txt 2018-12-03 17:52:44 +01:00
Francesco Gatti 4d30f0abd7 compile on x86 2018-12-03 17:37:24 +01:00
Francesco Gatti 415bd47697 opencv include fix 2018-12-03 15:52:02 +01:00
Alessio 09679d7bb6 voc 2018-09-18 16:27:09 +02:00
Francesco Gatti 029ad71673 readme ok 2018-09-15 09:04:23 +00:00
Francesco Gatti 6331724953 live detection 2018-09-15 08:57:43 +00:00
Tomasz b7d240ea6d opencv fix 2018-09-15 08:09:00 +00:00
Francesco Gatti 2cf8d8f6fc fp16 implementation, TODO deallocate in LayerWgs 2017-08-30 14:37:25 +00:00
Francesco Gatti a26ef98d2d yolo alternatives 2017-08-30 09:12:46 +00:00
Francesco Gatti 747fddab3f usage 2017-08-29 17:04:02 +00:00
Francesco Gatti b2d6dcd207 detect demo with mAP 2017-08-29 16:48:18 +00:00
Francesco Gatti ab45c24efc check control ok 2017-08-28 00:53:39 +02:00
Francesco Gatti e449209d01 0.3 box iou thresh 2017-08-25 06:31:00 -07:00
Francesco Gatti e93ed59c30 Merge branch 'cudnn5' of https://github.com/ceccocats/tkDNN into cudnn5 2017-08-25 06:09:33 -07:00
Francesco Gatti 168a1d8b27 color 2017-08-25 06:09:29 -07:00
Francesco Gatti 6c2f6bcf2e optimization2 2017-08-25 15:07:47 +02:00
Francesco Gatti 030e14d782 spalla overlap optimization 2017-08-25 11:41:29 +02:00
Francesco Gatti 00355cfcf4 delete repeats to be optimized 2017-08-22 07:52:51 -07:00
Francesco Gatti 0119b31455 class in box 2017-08-22 06:37:43 -07:00
Francesco Gatti 37b050a9c8 opencv compile not for dw 2017-08-22 02:33:08 -07:00
Francesco Gatti c41a0a09a6 version fix 2017-08-22 01:43:36 -07:00
Francesco Gatti 5595b8037b interpret 2017-08-22 01:32:59 -07:00
Francesco Gatti 5a52de17eb driveworks compile 2017-08-21 09:50:05 -07:00
Francesco Gatti 0aa9de4ce8 better rt inference 2017-08-21 12:10:17 +00:00
Francesco Gatti c63ac6b590 install 2017-08-21 12:30:34 +02:00
Francesco Gatti 2b4b9b8e49 F16 inference 2017-08-14 10:16:29 +00:00
Francesco Gatti 66ad6bb1d6 input dim fix 2017-08-14 11:57:28 +02:00
Francesco Gatti fc9fb4f153 support check 2017-08-14 11:48:29 +02:00
Francesco Gatti 6110fffbb5 inference fix 2017-08-14 11:36:48 +02:00
Francesco Gatti b3a369dc29 RTinference test 2017-08-14 11:24:23 +02:00
Francesco Gatti 81e5f6a97b int8 2017-08-14 10:29:17 +02:00
Francesco Gatti 2d7563d27c cast fix 2017-08-11 15:20:15 +00:00
Francesco Gatti 3b2f062dd9 tensorRT serialization OK 2017-08-11 17:17:05 +02:00
Francesco Gatti 57c9a6ec99 LEAKY serialized 2017-08-11 16:32:22 +02:00
Francesco Gatti 04f96048b6 memcpyasync 2017-08-11 13:56:36 +00:00
Francesco Gatti 3124f86878 stream in TRT plugin 2017-08-10 19:21:15 +02:00
Francesco Gatti 9a6058ac4a removed sync 2017-08-10 18:47:21 +02:00
Francesco Gatti aef39f6144 opencv fix 2017-08-10 14:30:55 +00:00
Francesco Gatti 266330009c opencv viz 2017-08-10 16:22:17 +02:00
Francesco Gatti b75fa637cb better print 2017-08-09 16:04:49 +00:00
Francesco Gatti 1c6888f312 auto download 2017-08-09 14:13:17 +00:00
Francesco Gatti 3215d5aab0 tiny yolo fix 2017-08-09 12:44:06 +02:00
Francesco Gatti d7ce952465 get regions 2017-08-08 17:17:24 +02:00
Francesco Gatti 0a9957ba18 network print 2017-08-08 14:59:25 +02:00
Francesco Gatti 7d570c0df4 tiny yolo not working 2017-08-07 15:05:48 +02:00
Francesco Gatti 34198a4e8d fix 2017-08-04 16:16:03 +00:00
Francesco Gatti b20a2e2902 fix 2017-08-04 10:45:07 +02:00
Francesco Gatti 0ff47ad6ba YOLO IN TENSORT :) 2017-08-03 16:50:57 +02:00
Francesco Gatti 4e189755cf yolo weights tar 2017-08-03 16:09:23 +02:00
Francesco Gatti 858b3501fa yolo TensorRT almost DONE 2017-08-03 15:52:08 +02:00
Francesco Gatti 2ef76209a1 LEAKY plugin 2017-08-03 13:25:33 +02:00
Francesco Gatti 4526e2767a NetworkRT (deallocations to be done) 2017-08-03 12:16:57 +02:00
Francesco Gatti e8355cee67 better network model 2017-08-01 23:03:02 +02:00
Francesco Gatti 300b0af5dd mnist RT ok 2017-08-01 20:58:24 +02:00
Francesco Gatti 714bd5f757 mnist tensorrt incomplete 2017-08-01 18:58:59 +02:00
Francesco Gatti bed0b57fad mnist tensor 2017-08-01 18:08:56 +02:00
Francesco Gatti ed5e5d58b5 TensorRT version 2017-08-01 17:51:49 +02:00
Francesco Gatti 1cfe70365f yolo test 2017-08-01 17:12:29 +02:00
Francesco Gatti b94931f9f7 yolo layers 2017-08-01 16:08:56 +02:00
Francesco Gatti 8e4b3c6c17 download test data 2017-07-26 01:46:25 -09:00
165 changed files with 25265 additions and 949 deletions
+12 -1
View File
@@ -2,4 +2,15 @@
build/
.vscode/
*.bin
*.pyc
*.pyc
*.prototxt
*.caffemodel
*.h5
*.tar.gz
*.weights
.idea/
*.hdf5
*.pk
*.table
demo/COCO_val2017
demo/BDD100K_val
+120 -11
View File
@@ -1,20 +1,129 @@
cmake_minimum_required(VERSION 2.8)
cmake_minimum_required(VERSION 3.5)
project (tkDNN)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fPIC -Wno-deprecated-declarations -Wno-unused-variable")
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include/tkDNN)
find_package(CUDA QUIET REQUIRED)
# project specific flags
if(DEBUG)
add_definitions(-DDEBUG)
endif()
cuda_include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include ${CUDA_INCLUDE_DIRS})
cuda_add_library(kernels SHARED src/kernels/activation_elu.cu)
add_definitions(-DTKDNN_PATH="${CMAKE_CURRENT_SOURCE_DIR}")
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include ${CUDA_INCLUDE_DIRS})
add_library(tkDNN SHARED src/Layer.cpp src/LayerWgs.cpp
src/Dense.cpp src/Activation.cpp src/Conv2d.cpp src/Flatten.cpp src/MulAdd.cpp src/Pooling.cpp src/Softmax.cpp
src/Network.cpp src/utils.cpp)
target_link_libraries(tkDNN kernels ${CUDA_LIBRARIES} ${CUDA_CUBLAS_LIBRARIES} -lcudnn)
#-------------------------------------------------------------------------------
# CUDA
#-------------------------------------------------------------------------------
find_package(CUDA 9.0 REQUIRED)
SET(CUDA_SEPARABLE_COMPILATION ON)
#set(CUDA_NVCC_FLAGS "${CUDA_NVCC_FLAGS} -arch=sm_30 --compiler-options '-fPIC'")
set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} --maxrregcount=32)
add_executable(test_simple tests/test/test.cpp)
find_package(CUDNN REQUIRED)
include_directories(${CUDNN_INCLUDE_DIR})
# compile
file(GLOB tkdnn_CUSRC "src/kernels/*.cu" "src/sorting.cu")
cuda_include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include ${CUDA_INCLUDE_DIRS} ${CUDNN_INCLUDE_DIRS})
cuda_add_library(kernels SHARED ${tkdnn_CUSRC})
#-------------------------------------------------------------------------------
# External Libraries
#-------------------------------------------------------------------------------
find_package(Eigen3 REQUIRED)
include_directories(${EIGEN3_INCLUDE_DIR})
find_package(OpenCV REQUIRED)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DOPENCV")
# gives problems in cross-compiling, probably malformed cmake config
#find_package(yaml-cpp REQUIRED)
#-------------------------------------------------------------------------------
# Build Libraries
#-------------------------------------------------------------------------------
file(GLOB tkdnn_SRC "src/*.cpp")
set(tkdnn_LIBS kernels ${CUDA_LIBRARIES} ${CUDA_CUBLAS_LIBRARIES} ${CUDNN_LIBRARIES} ${OpenCV_LIBS} yaml-cpp)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include ${CUDA_INCLUDE_DIRS} ${OPENCV_INCLUDE_DIRS} ${NVINFER_INCLUDES})
add_library(tkDNN SHARED ${tkdnn_SRC})
target_link_libraries(tkDNN ${tkdnn_LIBS})
#static
#add_library(tkDNN_static STATIC ${tkdnn_SRC})
#target_link_libraries(tkDNN_static ${tkdnn_LIBS})
# SMALL NETS
add_executable(test_simple tests/simple/test_simple.cpp)
target_link_libraries(test_simple tkDNN)
add_executable(test_mnist tests/mnist/test.cpp)
add_executable(test_mnist tests/mnist/test_mnist.cpp)
target_link_libraries(test_mnist tkDNN)
add_executable(test_mnistRT tests/mnist/test_mnistRT.cpp)
target_link_libraries(test_mnistRT tkDNN)
add_executable(test_imuodom tests/imuodom/imuodom.cpp)
target_link_libraries(test_imuodom tkDNN)
# DARKNET
file(GLOB darknet_SRC "tests/darknet/*.cpp")
foreach(test_SRC ${darknet_SRC})
get_filename_component(test_NAME "${test_SRC}" NAME_WE)
set(test_NAME test_${test_NAME})
add_executable(${test_NAME} ${test_SRC})
target_link_libraries(${test_NAME} tkDNN)
endforeach()
# MOBILENET
add_executable(test_mobilenetv2ssd tests/mobilenet/mobilenetv2ssd/mobilenetv2ssd.cpp)
target_link_libraries(test_mobilenetv2ssd tkDNN)
add_executable(test_bdd-mobilenetv2ssd tests/mobilenet/bdd-mobilenetv2ssd/bdd-mobilenetv2ssd.cpp)
target_link_libraries(test_bdd-mobilenetv2ssd tkDNN)
add_executable(test_mobilenetv2ssd512 tests/mobilenet/mobilenetv2ssd512/mobilenetv2ssd512.cpp)
target_link_libraries(test_mobilenetv2ssd512 tkDNN)
# BACKBONES
add_executable(test_resnet101 tests/backbones/resnet101/resnet101.cpp)
target_link_libraries(test_resnet101 tkDNN)
add_executable(test_dla34 tests/backbones/dla34/dla34.cpp)
target_link_libraries(test_dla34 tkDNN)
# CENTERNET
add_executable(test_resnet101_cnet tests/centernet/resnet101_cnet/resnet101_cnet.cpp)
target_link_libraries(test_resnet101_cnet tkDNN)
add_executable(test_dla34_cnet tests/centernet/dla34_cnet/dla34_cnet.cpp)
target_link_libraries(test_dla34_cnet tkDNN)
# DEMOS
add_executable(test_rtinference tests/test_rtinference/rtinference.cpp)
target_link_libraries(test_rtinference tkDNN)
add_executable(map_demo demo/demo/map.cpp)
target_link_libraries(map_demo tkDNN)
add_executable(demo demo/demo/demo.cpp)
target_link_libraries(demo tkDNN)
#-------------------------------------------------------------------------------
# Install
#-------------------------------------------------------------------------------
#if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
# set (CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/install"
# CACHE PATH "default install path" FORCE)
#endif()
message("install dir:" ${CMAKE_INSTALL_PREFIX})
install(DIRECTORY include/ DESTINATION include/)
install(TARGETS tkDNN kernels DESTINATION lib)
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/cmake/" # source directory
DESTINATION "share/tkDNN/cmake/" # target directory
)
+339
View File
@@ -0,0 +1,339 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
tkDNN
Copyright (C) 2017 Francesco Gatti
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.
+313 -65
View File
@@ -1,85 +1,333 @@
# tkDNN
tkDNN is a Deep Neural Network library built with cuDNN primitives specifically thought to work on NVIDIA TK1 board.<br>
The main scope is to do high performance inference on already trained models.
Currently supports the following layers:
tkDNN is a Deep Neural Network library built with cuDNN and tensorRT primitives, specifically thought to work on NVIDIA Jetson Boards. It has been tested on TK1(branch cudnn2), TX1, TX2, AGX Xavier and several discrete GPU.
The main goal of this project is to exploit NVIDIA boards as much as possible to obtain the best inference performance. It does not allow training.
* Dense, fully interconnected
* Activation (RELU, ELU, SIGMOID, TANH)
* Convolutional 2D
* Convolutional 3D
* Max and Average Pooling
* Flatten
* Data preprocessing
## Workflow
The recommended workflow follow these step:
* Build and train a model in Keras (on any PC)
* Export weights and bias
* Define the model on tkDNN
* Do inference (on TK1)
If you use tkDNN in your research, please cite one of the following papers. For use in commercial solutions, write at gattifrancesco@hotmail.it or refer to https://hipert.unimore.it/ .
## Compile the library
Build with cmake
```
Accepted paper @ IRC 2020, will soon be published.
M. Verucchi, L. Bartoli, F. Bagni, F. Gatti, P. Burgio and M. Bertogna, "Real-Time clustering and LiDAR-camera fusion on embedded platforms for self-driving cars", in proceedings in IEEE Robotic Computing (2020)
Accepted paper @ ETFA 2020, will soon be published.
M. Verucchi, G. Brilli, D. Sapienza, M. Verasani, M. Arena, F. Gatti, A. Capotondi, R. Cavicchioli, M. Bertogna, M. Solieri
"A Systematic Assessment of Embedded Neural Networks for Object Detection", in IEEE International Conference on Emerging Technologies and Factory Automation (2020)
```
## Results
Inference FPS of yolov4 with tkDNN, average of 1200 images with the same dimesion as the input size, on
* RTX 2080Ti (CUDA 10.2, TensorRT 7.0.0, Cudnn 7.6.5);
* Xavier AGX, Jetpack 4.3 (CUDA 10.0, CUDNN 7.6.3, tensorrt 6.0.1 );
* Tx2, Jetpack 4.2 (CUDA 10.0, CUDNN 7.3.1, tensorrt 5.0.6 );
* Jetson Nano, Jetpack 4.4 (CUDA 10.2, CUDNN 8.0.0, tensorrt 7.1.0 ).
| Platform | Network | FP32, B=1 | FP32, B=4 | FP16, B=1 | FP16, B=4 | INT8, B=1 | INT8, B=4 |
| :------: | :-----: | :-----: | :-----: | :-----: | :-----: | :-----: | :-----: |
| RTX 2080Ti | yolo4 320 | 118,59 |237,31 | 207,81 | 443,32 | 262,37 | 530,93 |
| RTX 2080Ti | yolo4 416 | 104,81 |162,86 | 169,06 | 293,78 | 206,93 | 353,26 |
| RTX 2080Ti | yolo4 512 | 92,98 |132,43 | 140,36 | 215,17 | 165,35 | 254,96 |
| RTX 2080Ti | yolo4 608 | 63,77 |81,53 | 111,39 | 152,89 | 127,79 | 184,72 |
| AGX Xavier | yolo4 320 | 26,78 |32,05 | 57,14 | 79,05 | 73,15 | 97,56 |
| AGX Xavier | yolo4 416 | 19,96 |21,52 | 41,01 | 49,00 | 50,81 | 60,61 |
| AGX Xavier | yolo4 512 | 16,58 |16,98 | 31,12 | 33,84 | 37,82 | 41,28 |
| AGX Xavier | yolo4 608 | 9,45 |10,13 | 21,92 | 23,36 | 27,05 | 28,93 |
| Tx2 | yolo4 320 | 11,18 | 12,07 | 15,32 | 16,31 | - | - |
| Tx2 | yolo4 416 | 7,30 | 7,58 | 9,45 | 9,90 | - | - |
| Tx2 | yolo4 512 | 5,96 | 5,95 | 7,22 | 7,23 | - | - |
| Tx2 | yolo4 608 | 3,63 | 3,65 | 4,67 | 4,70 | - | - |
| Nano | yolo4 320 | 4,23 | 4,55 | 6,14 | 6,53 | - | - |
| Nano | yolo4 416 | 2,88 | 3,00 | 3,90 | 4,04 | - | - |
| Nano | yolo4 512 | 2,32 | 2,34 | 3,02 | 3,04 | - | - |
| Nano | yolo4 608 | 1,40 | 1,41 | 1,92 | 1,93 | - | - |
## Index
- [tkDNN](#tkdnn)
- [Index](#index)
- [Dependencies](#dependencies)
- [About OpenCV](#about-opencv)
- [How to compile this repo](#how-to-compile-this-repo)
- [Workflow](#workflow)
- [How to export weights](#how-to-export-weights)
- [1)Export weights from darknet](#1export-weights-from-darknet)
- [2)Export weights for DLA34 and ResNet101](#2export-weights-for-dla34-and-resnet101)
- [3)Export weights for CenterNet](#3export-weights-for-centernet)
- [4)Export weights for MobileNetSSD](#4export-weights-for-mobilenetssd)
- [Run the demo](#run-the-demo)
- [FP16 inference](#fp16-inference)
- [INT8 inference](#int8-inference)
- [mAP demo](#map-demo)
- [Existing tests and supported networks](#existing-tests-and-supported-networks)
- [References](#references)
## Dependencies
This branch works on every NVIDIA GPU that supports the dependencies:
* CUDA 10.0
* CUDNN 7.603
* TENSORRT 6.01
* OPENCV 3.4
* yaml-cpp 0.5.2 (sudo apt install libyaml-cpp-dev)
## About OpenCV
To compile and install OpenCV4 with contrib us the script ```install_OpenCV4.sh```. It will download and compile OpenCV in Download folder.
```
bash scripts/install_OpenCV4.sh
```
When using openCV not compiled with contrib, comment the definition of OPENCV_CUDACONTRIBCONTRIB in include/tkDNN/DetectionNN.h. When commented, the preprocessing of the networks is computed on the CPU, otherwise on the GPU. In the latter case some milliseconds are saved in the end-to-end latency.
## How to compile this repo
Build with cmake. If using Ubuntu 18.04 a new version of cmake is needed (3.15 or above).
```
git clone https://github.com/ceccocats/tkDNN
cd tkDNN
mkdir build
cd build
cmake ..
cmake ..
make
```
## Test
There is a ready to use example on *test* directory, to try it you must generate the weights with Keras
## Workflow
Steps needed to do inference on tkDNN with a custom neural network.
* Build and train a NN model with your favorite framework.
* Export weights and bias for each layer and save them in a binary file (one for layer).
* Export outputs for each layer and save them in a binary file (one for layer).
* Create a new test and define the network, layer by layer using the weights extracted and the output to check the results.
* Do inference.
## How to export weights
Weights are essential for any network to run inference. For each test a folder organized as follow is needed (in the build folder):
```
cd tests
python test_model.py
test_nn
|---- layers/ (folder containing a binary file for each layer with the corresponding wieghts and bias)
|---- debug/ (folder containing a binary file for each layer with the corresponding outputs)
```
And then execute the inference on build directory
Therefore, once the weights have been exported, the folders layers and debug should be placed in the corresponding test.
### 1)Export weights from darknet
To export weights for NNs that are defined in darknet framework, use [this](https://git.hipert.unimore.it/fgatti/darknet.git) fork of darknet and follow these steps to obtain a correct debug and layers folder, ready for tkDNN.
```
git clone https://git.hipert.unimore.it/fgatti/darknet.git
cd darknet
make
mkdir layers debug
./darknet export <path-to-cfg-file> <path-to-weights> layers
```
N.b. Use compilation with CPU (leave GPU=0 in Makefile) if you also want debug.
### 2)Export weights for DLA34 and ResNet101
To get weights and outputs needed to run the tests dla34 and resnet101 use the Python script and the Anaconda environment included in the repository.
Create Anaconda environment and activate it:
```
conda env create -f file_name.yml
source activate env_name
python <script name>
```
### 3)Export weights for CenterNet
To get the weights needed to run Centernet tests use [this](https://github.com/sapienzadavide/CenterNet.git) fork of the original Centernet.
```
git clone https://github.com/sapienzadavide/CenterNet.git
```
* follow the instruction in the README.md and INSTALL.md
```
python demo.py --input_res 512 --arch resdcn_101 ctdet --demo /path/to/image/or/folder/or/video/or/webcam --load_model ../models/ctdet_coco_resdcn101.pth --exp_wo --exp_wo_dim 512
python demo.py --input_res 512 --arch dla_34 ctdet --demo /path/to/image/or/folder/or/video/or/webcam --load_model ../models/ctdet_coco_dla_2x.pth --exp_wo --exp_wo_dim 512
```
### 4)Export weights for MobileNetSSD
To get the weights needed to run Mobilenet tests use [this](https://github.com/mive93/pytorch-ssd) fork of a Pytorch implementation of SSD network.
```
git clone https://github.com/mive93/pytorch-ssd
cd pytorch-ssd
conda env create -f env_mobv2ssd.yml
python run_ssd_live_demo.py mb2-ssd-lite <pth-model-fil> <labels-file>
```
## Darknet Parser
tkDNN implement and easy parser for darknet cfg files, a network can be converted with *tk::dnn::darknetParser*:
```
// example of parsing yolo4
tk::dnn::Network *net = tk::dnn::darknetParser("yolov4.cfg", "yolov4/layers", "coco.names");
net->print();
```
All models from darknet are now parsed directly from cfg, you still need to export the weights with the descripted tools in the previus section.
<details>
<summary>Supported layers</summary>
convolutional
maxpool
avgpool
shortcut
upsample
route
reorg
region
yolo
</details>
<details>
<summary>Supported activations</summary>
relu
leaky
mish
</details>
## Run the demo
To run the an object detection demo follow these steps (example with yolov3):
```
rm yolo3_fp32.rt # be sure to delete(or move) old tensorRT files
./test_yolo3 # run the yolo test (is slow)
./demo yolo3_fp32.rt ../demo/yolo_test.mp4 y
```
In general the demo program takes 4 parameters:
```
./demo <network-rt-file> <path-to-video> <kind-of-network> <number-of-classes> <n-batches> <show-flag>
```
where
* ```<network-rt-file>``` is the rt file generated by a test
* ```<<path-to-video>``` is the path to a video file or a camera input
* ```<kind-of-network>``` is the type of network. Thee types are currently supported: ```y``` (YOLO family), ```c``` (CenterNet family) and ```m``` (MobileNet-SSD family)
* ```<number-of-classes>```is the number of classes the network is trained on
* ```<n-batches>``` number of batches to use in inference (N.B. you should first export TKDNN_BATCHSIZE to the required n_batches and create again the rt file for the network).
* ```<show-flag>``` if set to 0 the demo will not show the visualization but save the video into result.mp4 (if n-batches ==1)
N.b. By default it is used FP32 inference
![demo](https://user-images.githubusercontent.com/11562617/72547657-540e7800-388d-11ea-83c6-49dfea2a0607.gif)
### FP16 inference
To run the an object detection demo with FP16 inference follow these steps (example with yolov3):
```
export TKDNN_MODE=FP16 # set the half floating point optimization
rm yolo3_fp16.rt # be sure to delete(or move) old tensorRT files
./test_yolo3 # run the yolo test (is slow)
./demo yolo3_fp16.rt ../demo/yolo_test.mp4 y
```
N.b. Using FP16 inference will lead to some errors in the results (first or second decimal).
### INT8 inference
To run the an object detection demo with INT8 inference three environment variables need to be set:
* ```export TKDNN_MODE=INT8```: set the 8-bit integer optimization
* ```export TKDNN_CALIB_IMG_PATH=/path/to/calibration/image_list.txt``` : image_list.txt has in each line the absolute path to a calibration image
* ```export TKDNN_CALIB_LABEL_PATH=/path/to/calibration/label_list.txt```: label_list.txt has in each line the absolute path to a calibration label
You should provide image_list.txt and label_list.txt, using training images. However, if you want to quickly test the INT8 inference you can run (from this repo root folder)
```
bash scripts/download_validation.sh COCO
```
to automatically download COCO2017 validation (inside demo folder) and create those needed file. Use BDD insted of COCO to download BDD validation.
Then a complete example using yolo3 and COCO dataset would be:
```
export TKDNN_MODE=INT8
export TKDNN_CALIB_LABEL_PATH=../demo/COCO_val2017/all_labels.txt
export TKDNN_CALIB_IMG_PATH=../demo/COCO_val2017/all_images.txt
rm yolo3_int8.rt # be sure to delete(or move) old tensorRT files
./test_yolo3 # run the yolo test (is slow)
./demo yolo3_int8.rt ../demo/yolo_test.mp4 y
```
N.B.
* Using INT8 inference will lead to some errors in the results.
* The test will be slower: this is due to the INT8 calibration, which may take some time to complete.
* INT8 calibration requires TensorRT version greater than or equal to 6.0
* Only 100 images are used to create the calibration table by default (set in the code).
### BatchSize bigger than 1
```
export TKDNN_BATCHSIZE=2
# build tensorRT files
```
This will create a TensorRT file with the desidered **max** batch size.
The test will still run with a batch of 1, but the created tensorRT can manage the desidered batch size.
### Test batch Inference
This will test the network with random input and check if the output of each batch is the same.
```
./test_rtinference <network-rt-file> <number-of-batches>
# <number-of-batches> should be less or equal to the max batch size of the <network-rt-file>
# example
export TKDNN_BATCHSIZE=4 # set max batch size
rm yolo3_fp32.rt # be sure to delete(or move) old tensorRT files
./test_yolo3 # build RT file
./test_rtinference yolo3_fp32.rt 4 # test with a batch size of 4
```
## mAP demo
To compute mAP, precision, recall and f1score, run the map_demo.
A validation set is needed.
To download COCO_val2017 (80 classes) run (form the root folder):
```
bash scripts/download_validation.sh COCO
```
To download Berkeley_val (10 classes) run (form the root folder):
```
bash scripts/download_validation.sh BDD
```
To compute the map, the following parameters are needed:
```
./map_demo <network rt> <network type [y|c|m]> <labels file path> <config file path>
```
where
* ```<network rt>```: rt file of a chosen network on which compute the mAP.
* ```<network type [y|c|m]>```: type of network. Right now only y(yolo), c(centernet) and m(mobilenet) are allowed
* ```<labels file path>```: path to a text file containing all the paths of the ground-truth labels. It is important that all the labels of the ground-truth are in a folder called 'labels'. In the folder containing the folder 'labels' there should be also a folder 'images', containing all the ground-truth images having the same same as the labels. To better understand, if there is a label path/to/labels/000001.txt there should be a corresponding image path/to/images/000001.jpg.
* ```<config file path>```: path to a yaml file with the parameters needed for the mAP computation, similar to demo/config.yaml
Example:
```
cd build
./tkDNNtest
```
this should output the same prediction as Keras.
## Simple example
Here is a example of the entire workflow on a simple model.
Using the following Keras model save it to a file
```python
model = Sequential()
model.add(Reshape((20, 1), input_shape=(20)))
model.add(Dense(256))
model.compile()
# save model
model.save("path/to/model.h5")
./map_demo dla34_cnet_FP32.rt c ../demo/COCO_val2017/all_labels.txt ../demo/config.yaml
```
After the model is created the weights can be exported for tkDNN inference
```
python weights_exporter model.h5 dense --output=weights/path
```
the exporter take as arguments, in order:
* input model
* layer type ["dense", "conv2d", conv3d"]
* { layer type ["dense", "conv2d", conv3d"] for each layer to export }
* optional argument --output define path where export weights
This demo also creates a json file named ```net_name_COCO_res.json``` containing all the detections computed. The detections are in COCO format, the correct format to subit the results to [CodaLab COCO detection challenge](https://competitions.codalab.org/competitions/20794#participate).
Then we can create a c++ program to do inference on tk1
```c++
#include<tkdnn.h> //library include
## Existing tests and supported networks
//Network object
tkDNN::Network net;
//input dimension
tkDNN::dataDim_t dim(1, 20, 1, 1, 1);
//Dense layer
tkDNN::Dense d0(&net, dim, 256, "weights/path", "bias/path");
| Test Name | Network | Dataset | N Classes | Input size | Weights |
| :---------------- | :-------------------------------------------- | :-----------------------------------------------------------: | :-------: | :-----------: | :------------------------------------------------------------------------ |
| yolo | YOLO v2<sup>1</sup> | [COCO 2014](http://cocodataset.org/) | 80 | 608x608 | [weights](https://cloud.hipert.unimore.it/s/nf4PJ3k8bxBETwL/download) |
| yolo_224 | YOLO v2<sup>1</sup> | [COCO 2014](http://cocodataset.org/) | 80 | 224x224 | weights |
| yolo_berkeley | YOLO v2<sup>1</sup> | [BDD100K ](https://bair.berkeley.edu/blog/2018/05/30/bdd/) | 10 | 416x736 | weights |
| yolo_relu | YOLO v2 (with ReLU, not Leaky)<sup>1</sup> | [COCO 2014](http://cocodataset.org/) | 80 | 416x416 | weights |
| yolo_tiny | YOLO v2 tiny<sup>1</sup> | [COCO 2014](http://cocodataset.org/) | 80 | 416x416 | [weights](https://cloud.hipert.unimore.it/s/m3orfJr8pGrN5mQ/download) |
| yolo_voc | YOLO v2<sup>1</sup> | [VOC ](http://host.robots.ox.ac.uk/pascal/VOC/) | 21 | 416x416 | [weights](https://cloud.hipert.unimore.it/s/DJC5Fi2pEjfNDP9/download) |
| yolo3 | YOLO v3<sup>2</sup> | [COCO 2014](http://cocodataset.org/) | 80 | 416x416 | [weights](https://cloud.hipert.unimore.it/s/jPXmHyptpLoNdNR/download) |
| yolo3_512 | YOLO v3<sup>2</sup> | [COCO 2017](http://cocodataset.org/) | 80 | 512x512 | [weights](https://cloud.hipert.unimore.it/s/RGecMeGLD4cXEWL/download) |
| yolo3_berkeley | YOLO v3<sup>2</sup> | [BDD100K ](https://bair.berkeley.edu/blog/2018/05/30/bdd/) | 10 | 320x544 | [weights](https://cloud.hipert.unimore.it/s/o5cHa4AjTKS64oD/download) |
| yolo3_coco4 | YOLO v3<sup>2</sup> | [COCO 2014](http://cocodataset.org/) | 4 | 416x416 | [weights](https://cloud.hipert.unimore.it/s/o27NDzSAartbyc4/download) |
| yolo3_flir | YOLO v3<sup>2</sup> | [FREE FLIR](https://www.flir.com/oem/adas/adas-dataset-form/) | 3 | 320x544 | [weights](https://cloud.hipert.unimore.it/s/62DECncmF6bMMiH/download) |
| yolo3_tiny | YOLO v3 tiny<sup>2</sup> | [COCO 2014](http://cocodataset.org/) | 80 | 416x416 | [weights](https://cloud.hipert.unimore.it/s/LMcSHtWaLeps8yN/download) |
| yolo3_tiny512 | YOLO v3 tiny<sup>2</sup> | [COCO 2017](http://cocodataset.org/) | 80 | 512x512 | [weights](https://cloud.hipert.unimore.it/s/8Zt6bHwHADqP4JC/download) |
| dla34 | Deep Leayer Aggreagtion (DLA) 34<sup>3</sup> | [COCO 2014](http://cocodataset.org/) | 80 | 224x224 | weights |
| dla34_cnet | Centernet (DLA34 backend)<sup>4</sup> | [COCO 2017](http://cocodataset.org/) | 80 | 512x512 | [weights](https://cloud.hipert.unimore.it/s/KRZBbCQsKAtQwpZ/download) |
| mobilenetv2ssd | Mobilnet v2 SSD Lite<sup>5</sup> | [VOC ](http://host.robots.ox.ac.uk/pascal/VOC/) | 21 | 300x300 | [weights](https://cloud.hipert.unimore.it/s/x4ZfxBKN23zAJQp/download) |
| mobilenetv2ssd512 | Mobilnet v2 SSD Lite<sup>5</sup> | [COCO 2017](http://cocodataset.org/) | 81 | 512x512 | [weights](https://cloud.hipert.unimore.it/s/pdCw2dYyHMJrcEM/download) |
| resnet101 | Resnet 101<sup>6</sup> | [COCO 2014](http://cocodataset.org/) | 80 | 224x224 | weights |
| resnet101_cnet | Centernet (Resnet101 backend)<sup>4</sup> | [COCO 2017](http://cocodataset.org/) | 80 | 512x512 | [weights](https://cloud.hipert.unimore.it/s/5BTjHMWBcJk8g3i/download) |
| csresnext50-panet-spp | Cross Stage Partial Network <sup>7</sup> | [COCO 2014](http://cocodataset.org/) | 80 | 416x416 | [weights](https://cloud.hipert.unimore.it/s/Kcs4xBozwY4wFx8/download) |
| yolo4 | Yolov4 <sup>8</sup> | [COCO 2017](http://cocodataset.org/) | 80 | 416x416 | [weights](https://cloud.hipert.unimore.it/s/d97CFzYqCPCp5Hg/download) |
| yolo4_berkeley | Yolov4 <sup>8</sup> | [BDD100K ](https://bair.berkeley.edu/blog/2018/05/30/bdd/) | 10 | 540x320 | [weights](https://cloud.hipert.unimore.it/s/nkWFa5fgb4NTdnB/download) |
| yolo4tiny | Yolov4 tiny | [COCO 2017](http://cocodataset.org/) | 80 | 416x416 | [weights](https://cloud.hipert.unimore.it/s/iRnc4pSqmx78gJs/download) |
//here load the input data to CUDA
//value_type is an alias of "float"
value_type *data_d = [...]
//do inference
value_type *output_d = d0.infer(dim, data_d);
//dim will be updated with the output dimension
```
The result is finally stored on output_d in device memory.
## References
1. Redmon, Joseph, and Ali Farhadi. "YOLO9000: better, faster, stronger." Proceedings of the IEEE conference on computer vision and pattern recognition. 2017.
2. Redmon, Joseph, and Ali Farhadi. "Yolov3: An incremental improvement." arXiv preprint arXiv:1804.02767 (2018).
3. Yu, Fisher, et al. "Deep layer aggregation." Proceedings of the IEEE conference on computer vision and pattern recognition. 2018.
4. Zhou, Xingyi, Dequan Wang, and Philipp Krähenbühl. "Objects as points." arXiv preprint arXiv:1904.07850 (2019).
5. Sandler, Mark, et al. "Mobilenetv2: Inverted residuals and linear bottlenecks." Proceedings of the IEEE conference on computer vision and pattern recognition. 2018.
6. He, Kaiming, et al. "Deep residual learning for image recognition." Proceedings of the IEEE conference on computer vision and pattern recognition. 2016.
7. Wang, Chien-Yao, et al. "CSPNet: A New Backbone that can Enhance Learning Capability of CNN." arXiv preprint arXiv:1911.11929 (2019).
8. Bochkovskiy, Alexey, Chien-Yao Wang, and Hong-Yuan Mark Liao. "YOLOv4: Optimal Speed and Accuracy of Object Detection." arXiv preprint arXiv:2004.10934 (2020).
+66
View File
@@ -0,0 +1,66 @@
# find the library
if(CUDA_FOUND)
find_cuda_helper_libs(cudnn)
set(CUDNN_LIBRARY ${CUDA_cudnn_LIBRARY} CACHE FILEPATH "location of the cuDNN library")
unset(CUDA_cudnn_LIBRARY CACHE)
find_cuda_helper_libs(nvinfer)
set(NVINFER_LIBRARY ${CUDA_nvinfer_LIBRARY} CACHE FILEPATH "location of the nvinfer library")
unset(CUDA_nvinfer_LIBRARY CACHE)
endif()
# find the include
if(CUDNN_LIBRARY)
find_path(CUDNN_INCLUDE_DIR
cudnn.h
PATHS ${CUDA_TOOLKIT_INCLUDE}
DOC "location of cudnn.h"
NO_DEFAULT_PATH
)
if(NOT CUDNN_INCLUDE_DIR)
find_path(CUDNN_INCLUDE_DIR
cudnn.h
DOC "location of cudnn.h"
)
endif()
message("-- Found CUDNN: " ${CUDNN_LIBRARY})
message("-- Found CUDNN include: " ${CUDNN_INCLUDE_DIR})
endif()
if(NVINFER_LIBRARY)
find_path(NVINFER_INCLUDE_DIR
NvInfer.h
PATHS ${CUDA_TOOLKIT_INCLUDE}
DOC "location of NvInfer.h"
NO_DEFAULT_PATH
)
if(NOT NVINFER_INCLUDE_DIR)
find_path(NVINFER_INCLUDE_DIR
NvInfer.h
DOC "location of NvInfer.h"
)
endif()
message("-- Found NVINFER: " ${NVINFER_LIBRARY})
message("-- Found NVINFER include: " ${NVINFER_INCLUDE_DIR})
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(CUDNN
FOUND_VAR CUDNN_FOUND
REQUIRED_VARS
CUDNN_LIBRARY
CUDNN_INCLUDE_DIR
VERSION_VAR CUDNN_VERSION
)
if(CUDNN_FOUND)
set(CUDNN_LIBRARIES ${CUDNN_LIBRARY} ${NVINFER_LIBRARY})
set(CUDNN_INCLUDE_DIRS ${CUDNN_INCLUDE_DIR} ${NVINFER_INCLUDE_DIR})
endif()
set(CUDNN_FOUND true)
+24
View File
@@ -0,0 +1,24 @@
message("-- Found tkDNN")
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR})
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --std=c++11 -fPIC")
find_package(CUDA REQUIRED)
find_package(OpenCV REQUIRED)
find_package(CUDNN REQUIRED)
set(tkDNN_INCLUDE_DIRS
${CUDA_INCLUDE_DIRS}
${OPENCV_INCLUDE_DIRS}
${CUDNN_INCLUDE_DIRS}
)
set(tkDNN_LIBRARIES
tkDNN
kernels
${CUDA_LIBRARIES}
${CUDA_CUBLAS_LIBRARIES}
${CUDNN_LIBRARIES}
${OpenCV_LIBS}
)
set(tkDNN_FOUND true)
+7
View File
@@ -0,0 +1,7 @@
classes : 80 #number of classes
map_points : 101 #number of recall points (0 for all, 101 for COCO, 11 PascalVOC)
map_levels : 10 #number of IoU step for the AP
map_step : 0.05 #step of IoU
IoU_thresh : 0.5 #starting IoU threshold
conf_thresh : 0.0 #threshold on the condifence of the bbox
verbose : false #print on screen information
+7
View File
@@ -0,0 +1,7 @@
classes : 3 #number of classes
map_points : 101 #number of recall points (0 for all, 101 for COCO, 11 PascalVOC)
map_levels : 10 #number of IoU step for the AP
map_step : 0.05 #step of IoU
IoU_thresh : 0.5 #starting IoU threshold
conf_thresh : 0.0 #threshold on the condifence of the bbox
verbose : false #print on screen information
+139
View File
@@ -0,0 +1,139 @@
#include <iostream>
#include <signal.h>
#include <stdlib.h> /* srand, rand */
#include <unistd.h>
#include <mutex>
#include "CenternetDetection.h"
#include "MobilenetDetection.h"
#include "Yolo3Detection.h"
bool gRun;
bool SAVE_RESULT = false;
void sig_handler(int signo) {
std::cout<<"request gateway stop\n";
gRun = false;
}
int main(int argc, char *argv[]) {
std::cout<<"detection\n";
signal(SIGINT, sig_handler);
std::string net = "yolo3_berkeley.rt";
if(argc > 1)
net = argv[1];
std::string input = "../demo/yolo_test.mp4";
if(argc > 2)
input = argv[2];
char ntype = 'y';
if(argc > 3)
ntype = argv[3][0];
int n_classes = 80;
if(argc > 4)
n_classes = atoi(argv[4]);
int n_batch = 1;
if(argc > 5)
n_batch = atoi(argv[5]);
bool show = true;
if(argc > 6)
show = atoi(argv[6]);
if(n_batch < 1 || n_batch > 64)
FatalError("Batch dim not supported");
if(!show)
SAVE_RESULT = true;
tk::dnn::Yolo3Detection yolo;
tk::dnn::CenternetDetection cnet;
tk::dnn::MobilenetDetection mbnet;
tk::dnn::DetectionNN *detNN;
switch(ntype)
{
case 'y':
detNN = &yolo;
break;
case 'c':
detNN = &cnet;
break;
case 'm':
detNN = &mbnet;
n_classes++;
break;
default:
FatalError("Network type not allowed (3rd parameter)\n");
}
detNN->init(net, n_classes, n_batch);
gRun = true;
cv::VideoCapture cap(input);
if(!cap.isOpened())
gRun = false;
else
std::cout<<"camera started\n";
cv::VideoWriter resultVideo;
if(SAVE_RESULT) {
int w = cap.get(cv::CAP_PROP_FRAME_WIDTH);
int h = cap.get(cv::CAP_PROP_FRAME_HEIGHT);
resultVideo.open("result.mp4", cv::VideoWriter::fourcc('M','P','4','V'), 30, cv::Size(w, h));
}
cv::Mat frame;
if(show)
cv::namedWindow("detection", cv::WINDOW_NORMAL);
std::vector<cv::Mat> batch_frame;
std::vector<cv::Mat> batch_dnn_input;
while(gRun) {
batch_dnn_input.clear();
batch_frame.clear();
for(int bi=0; bi< n_batch; ++bi){
cap >> frame;
if(!frame.data)
break;
batch_frame.push_back(frame);
// this will be resized to the net format
batch_dnn_input.push_back(frame.clone());
}
if(!frame.data)
break;
//inference
detNN->update(batch_dnn_input, n_batch);
detNN->draw(batch_frame);
if(show){
for(int bi=0; bi< n_batch; ++bi){
cv::imshow("detection", batch_frame[bi]);
cv::waitKey(1);
}
}
if(n_batch == 1 && SAVE_RESULT)
resultVideo << frame;
}
std::cout<<"detection end\n";
double mean = 0;
std::cout<<COL_GREENB<<"\n\nTime stats:\n";
std::cout<<"Min: "<<*std::min_element(detNN->stats.begin(), detNN->stats.end())/n_batch<<" ms\n";
std::cout<<"Max: "<<*std::max_element(detNN->stats.begin(), detNN->stats.end())/n_batch<<" ms\n";
for(int i=0; i<detNN->stats.size(); i++) mean += detNN->stats[i]; mean /= detNN->stats.size();
std::cout<<"Avg: "<<mean/n_batch<<" ms\t"<<1000/(mean/n_batch)<<" FPS\n"<<COL_END;
return 0;
}
+235
View File
@@ -0,0 +1,235 @@
#include <iostream>
#include <signal.h>
#include <stdlib.h> /* srand, rand */
#include <unistd.h>
#include <mutex>
#include "utils.h"
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/videoio.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include "Yolo3Detection.h"
#include "CenternetDetection.h"
#include "MobilenetDetection.h"
#include "evaluation.h"
#include <map>
void convertFilename(std::string &filename,const std::string l_folder, const std::string i_folder, const std::string l_ext,const std::string i_ext)
{
filename.replace(filename.find(l_folder),l_folder.length(),i_folder);
filename.replace(filename.find(l_ext),l_ext.length(),i_ext);
}
int main(int argc, char *argv[])
{
char ntype = 'y';
const char *config_filename = "../demo/config.yaml";
const char * net = "yolo3.rt";
const char * labels_path = "../demo/COCO_val2017/all_labels.txt";
bool show = false;
bool write_dets = false;
bool write_res_on_file = true;
bool write_coco_json = true;
int n_images = 5000;
bool verbose;
int classes, map_points, map_levels;
float map_step, IoU_thresh, conf_thresh;
double vm_total = 0, rss_total = 0;
double vm, rss;
//read args
if(argc > 1)
net = argv[1];
if(argc > 2)
ntype = argv[2][0];
if(argc > 3)
labels_path = argv[3];
if(argc > 4)
config_filename = argv[4];
//check if files needed exist
if(!fileExist(config_filename))
FatalError("Wrong config file path.");
if(!fileExist(net))
FatalError("Wrong net file path.");
if(!fileExist(labels_path))
FatalError("Wrong labels file path.");
//read mAP parameters
tk::dnn::readmAPParams( config_filename, classes, map_points, map_levels, map_step,
IoU_thresh, conf_thresh, verbose);
//extract network name from rt path
std::string net_name;
removePathAndExtension(net, net_name);
std::cout<<"Network: "<<net_name<<std::endl;
//open files (if needed)
std::ofstream times, memory, coco_json;
if(write_coco_json){
coco_json.open(net_name+"_COCO_res.json");
coco_json << "[\n";
}
if(write_res_on_file){
times.open("times_"+net_name+".csv");
memory.open("memory.csv", std::ios_base::app);
memory<<net<<";";
}
// instantiate detector
tk::dnn::Yolo3Detection yolo;
tk::dnn::CenternetDetection cnet;
tk::dnn::MobilenetDetection mbnet;
tk::dnn::DetectionNN *detNN;
int n_classes = classes;
switch(ntype){
case 'y':
detNN = &yolo;
break;
case 'c':
detNN = &cnet;
break;
case 'm':
detNN = &mbnet;
n_classes++;
break;
default:
FatalError("Network type not allowed (3rd parameter)\n");
}
detNN->init(net, n_classes);
//read images
std::ifstream all_labels(labels_path);
std::string l_filename;
std::vector<tk::dnn::Frame> images;
std::vector<tk::dnn::box> detected_bbox;
std::cout<<"Reading groundtruth and generating detections"<<std::endl;
if(show)
cv::namedWindow("detection", cv::WINDOW_NORMAL);
int images_done;
for (images_done=0 ; std::getline(all_labels, l_filename) && images_done < n_images ; ++images_done) {
std::cout <<COL_ORANGEB<< "Images done:\t" << images_done<< "\n"<<COL_END;
tk::dnn::Frame f;
f.lFilename = l_filename;
f.iFilename = l_filename;
convertFilename(f.iFilename, "labels", "images", ".txt", ".jpg");
// read frame
if(!fileExist(f.iFilename.c_str()))
FatalError("Wrong image file path.");
cv::Mat frame = cv::imread(f.iFilename.c_str(), cv::IMREAD_COLOR);
std::vector<cv::Mat> batch_frames;
batch_frames.push_back(frame);
int height = frame.rows;
int width = frame.cols;
if(!frame.data)
break;
std::vector<cv::Mat> batch_dnn_input;
batch_dnn_input.push_back(frame.clone());
//inference
detected_bbox.clear();
detNN->update(batch_dnn_input,1,write_res_on_file, &times, write_coco_json);
detNN->draw(batch_frames);
detected_bbox = detNN->detected;
if(write_coco_json)
printJsonCOCOFormat(&coco_json, f.iFilename.c_str(), detected_bbox, classes, width, height);
std::ofstream myfile;
if(write_dets)
myfile.open ("det/"+f.lFilename.substr(f.lFilename.find("labels/") + 7));
// save detections labels
for(auto d:detected_bbox){
//convert detected bb in the same format as label
//<x_center>/<image_width> <y_center>/<image_width> <width>/<image_width> <height>/<image_width>
tk::dnn::BoundingBox b;
b.x = (d.x + d.w/2) / width;
b.y = (d.y + d.h/2) / height;
b.w = d.w / width;
b.h = d.h / height;
b.prob = d.prob;
b.cl = d.cl;
f.det.push_back(b);
if(write_dets)
myfile << d.cl << " "<< d.prob << " "<< b.x << " "<< b.y << " "<< b.w << " "<< b.h <<"\n";
if(show)// draw rectangle for detection
cv::rectangle(batch_frames[0], cv::Point(d.x, d.y), cv::Point(d.x + d.w, d.y + d.h), cv::Scalar(0, 0, 255), 2);
}
if(write_dets)
myfile.close();
// read and save groundtruth labels
if(fileExist(f.lFilename.c_str()))
{
std::ifstream labels(l_filename);
for(std::string line; std::getline(labels, line); ){
std::istringstream in(line);
tk::dnn::BoundingBox b;
in >> b.cl >> b.x >> b.y >> b.w >> b.h;
b.prob = 1;
b.truthFlag = 1;
f.gt.push_back(b);
if(show)// draw rectangle for groundtruth
cv::rectangle(batch_frames[0], cv::Point((b.x-b.w/2)*width, (b.y-b.h/2)*height), cv::Point((b.x+b.w/2)*width,(b.y+b.h/2)*height), cv::Scalar(0, 255, 0), 2);
}
}
images.push_back(f);
if(show){
cv::imshow("detection", batch_frames[0]);
cv::waitKey(0);
}
getMemUsage(vm, rss);
vm_total += vm;
rss_total += rss;
}
if(write_coco_json){
coco_json.seekp (coco_json.tellp() - std::streampos(2));
coco_json << "\n]\n";
coco_json.close();
}
std::cout << "Avg VM[MB]: " << vm_total/images_done/1024.0 << ";Avg RSS[MB]: " << rss_total/images_done/1024.0 << std::endl;
//compute mAP
double AP = tk::dnn::computeMapNIoULevels(images,classes,IoU_thresh,conf_thresh, map_points, map_step, map_levels, verbose, write_res_on_file, net_name);
std::cout<<"mAP "<<IoU_thresh<<":"<<IoU_thresh+map_step*(map_levels-1)<<" = "<<AP<<std::endl;
//compute average precision, recall and f1score
tk::dnn::computeTPFPFN(images,classes,IoU_thresh,conf_thresh, verbose, write_res_on_file, net_name);
if(write_res_on_file){
memory<<vm_total/images_done/1024.0<<";"<<rss_total/images_done/1024.0<<"\n";
times.close();
memory.close();
}
return 0;
}
Binary file not shown.
+7
View File
@@ -0,0 +1,7 @@
FROM ceccocats/tkdnn:latest
LABEL maintainer "Francesco Gatti"
RUN cd && git clone https://github.com/ceccocats/tkDNN.git && cd tkDNN && mkdir build && cd build \
&& cmake .. && make -j12
+57
View File
@@ -0,0 +1,57 @@
FROM nvidia/cuda:10.2-cudnn7-devel-ubuntu18.04
LABEL maintainer "Francesco Gatti"
ADD nv-tensorrt-repo-ubuntu1804-cuda10.2-trt7.0.0.11-ga-20191216_1-1_amd64.deb /tmp/trt.deb
RUN apt-get update && dpkg -i /tmp/trt.deb && rm /tmp/trt.deb && apt-get update
RUN apt install -y libnvinfer7=7.0.0-1+cuda10.2 libnvinfer-dev=7.0.0-1+cuda10.2
RUN DEBIAN_FRONTEND=noninteractive apt install -y git wget libeigen3-dev libyaml-cpp-dev
RUN cd /tmp && \
wget https://github.com/Kitware/CMake/releases/download/v3.17.3/cmake-3.17.3-Linux-x86_64.sh && \
chmod +x cmake-3.17.3-Linux-x86_64.sh && \
./cmake-3.17.3-Linux-x86_64.sh --prefix=/usr/local --exclude-subdir --skip-license && \
rm ./cmake-3.17.3-Linux-x86_64.sh
RUN echo "INSTALL OPENCV"
RUN apt-get install -y build-essential \
unzip \
pkg-config \
libjpeg-dev \
libpng-dev \
libtiff-dev \
libavcodec-dev \
libavformat-dev \
libswscale-dev \
libv4l-dev \
libxvidcore-dev \
libx264-dev \
libgtk-3-dev \
libatlas-base-dev \
gfortran \
libgstreamer1.0-dev \
libgstreamer-plugins-base1.0-dev \
libdc1394-22-dev \
libavresample-dev
RUN cd && wget https://github.com/opencv/opencv/archive/4.3.0.tar.gz && tar -xf 4.3.0.tar.gz && rm *.tar.gz
RUN cd && wget https://github.com/opencv/opencv_contrib/archive/4.3.0.tar.gz && tar -xf 4.3.0.tar.gz && rm *.tar.gz
RUN cd && \
cd opencv-4.3.0 && mkdir build && cd build && \
cmake -D CMAKE_BUILD_TYPE=RELEASE \
-D CMAKE_INSTALL_PREFIX=/usr/local \
-D INSTALL_PYTHON_EXAMPLES=OFF \
-D INSTALL_C_EXAMPLES=OFF \
-D OPENCV_EXTRA_MODULES_PATH='~/opencv_contrib-4.3.0/modules' \
-D BUILD_EXAMPLES=OFF \
-D WITH_CUDA=ON \
-D CUDA_ARCH_BIN=7.2 \
-D CUDA_ARCH_PTX="" \
-D ENABLE_FAST_MATH=ON \
-D CUDA_FAST_MATH=ON \
-D WITH_CUBLAS=ON \
-D WITH_LIBV4L=ON \
-D WITH_GSTREAMER=ON \
-D WITH_GSTREAMER_0_10=OFF \
-D WITH_TBB=ON \
../ && make -j12 && make install
RUN apt clean
+21
View File
@@ -0,0 +1,21 @@
# Use the prebuilt image
```
# build image
docker build -t tkdnn:build -f Dockerfile .
```
# Build Base Docker image
```
# make nvidia docker working
# follow this guide: https://github.com/NVIDIA/nvidia-docker
# dowload tensorrt
# from: https://developer.nvidia.com/compute/machine-learning/tensorrt/secure/7.0/7.0.0.11/local_repo/nv-tensorrt-repo-ubuntu1804-cuda10.2-trt7.0.0.11-ga-20191216_1-1_amd64.deb
# build image
docker build -t ceccocats/tkdnn:latest -f Dockerfile.base .
# run image
docker run -ti --gpus all --rm ceccocats/tkdnn:latest bash
```
-226
View File
@@ -1,226 +0,0 @@
#ifndef LAYER_H
#define LAYER_H
#include<iostream>
#include "utils.h"
#include "Network.h"
namespace tkDNN {
/**
Data rapresentation beetween layers
n = batch size
c = channels
h = heigth (lines)
w = width (rows)
l = lenght (3rd dimension)
*/
struct dataDim_t {
int n, c, h, w, l;
dataDim_t() : n(1), c(1), h(1), w(1), l(1) {};
dataDim_t(int _n, int _c, int _h, int _w, int _l = 1) :
n(_n), c(_c), h(_h), w(_w), l(_l) {};
void print() {
std::cout<<"Data dim: "<<n<<" "<<c<<" "<<h<<" "<<w<<" "<<l<<"\n";
}
int tot() {
return n*c*h*w*l;
}
};
/**
Simple layer Father class
*/
class Layer {
public:
Layer(Network *net, dataDim_t input_dim);
virtual ~Layer();
virtual value_type* infer(dataDim_t &dim, value_type* srcData) {
std::cout<<"No infer action for this layer\n";
return NULL;
}
dataDim_t input_dim, output_dim;
protected:
Network *net;
cudnnTensorDescriptor_t srcTensorDesc, dstTensorDesc;
};
/**
Father class of all layer that need to load trained weights
*/
class LayerWgs : public Layer {
public:
LayerWgs(Network *net, dataDim_t input_dim,
int inputs, int outputs, int kh, int kw, int kt,
const char* fname_weights, const char* fname_bias);
virtual ~LayerWgs();
protected:
int inputs, outputs;
std::string weights_path, bias_path;
value_type *data_h, *data_d;
value_type *bias_h, *bias_d;
};
/**
Dense (full interconnection) layer
*/
class Dense : public LayerWgs {
public:
Dense(Network *net, dataDim_t in_dim, int out_ch,
const char* fname_weights, const char* fname_bias);
virtual ~Dense();
virtual value_type* infer(dataDim_t &dim, value_type* srcData);
protected:
value_type *dstData; //where results will be putted
};
/**
Activation layer (it doesnt need weigths)
*/
class Activation : public Layer {
public:
Activation(Network *net, dataDim_t input_dim, cudnnActivationMode_t act_mode);
virtual ~Activation();
virtual value_type* infer(dataDim_t &dim, value_type* srcData);
protected:
cudnnActivationMode_t act_mode;
cudnnActivationDescriptor_t activDesc;
value_type *dstData; //where results will be putted
};
/**
Convolutional 2D layer
*/
class Conv2d : public LayerWgs {
public:
Conv2d(Network *net, dataDim_t in_dim, int out_ch,
int kernelH, int kernelW, int strideH, int strideW,
const char* fname_weights, const char* fname_bias);
virtual ~Conv2d();
virtual value_type* infer(dataDim_t &dim, value_type* srcData);
protected:
value_type *dstData; //where results will be putted
int kernelH, kernelW, strideH, strideW;
cudnnFilterDescriptor_t filterDesc;
cudnnConvolutionDescriptor_t convDesc;
cudnnConvolutionFwdAlgo_t algo;
cudnnTensorDescriptor_t biasTensorDesc;
void* workSpace;
size_t ws_sizeInBytes;
};
/**
Flatten layer
is actually a matrix transposition
*/
class Flatten : public Layer {
public:
Flatten(Network *net, dataDim_t input_dim);
virtual ~Flatten();
virtual value_type* infer(dataDim_t &dim, value_type* srcData);
protected:
value_type *dstData; //where results will be putted
};
/**
MulAdd layer
apply a multiplication and then an addition for each data
*/
class MulAdd : public Layer {
public:
MulAdd(Network *net, dataDim_t input_dim, value_type mul, value_type add);
virtual ~MulAdd();
virtual value_type* infer(dataDim_t &dim, value_type* srcData);
protected:
value_type mul, add;
value_type *dstData, *add_vector; //where results will be putted
};
/**
Avaible pooling functions (padding on tkDNN is not supported)
*/
typedef enum {
POOLING_MAX = 0,
POOLING_AVERAGE = 1, // count for average includes padded values
POOLING_AVERAGE_EXCLUDE_PADDING = 2 // count for average does not include padded values
} tkdnnPoolingMode_t;
/**
Pooling layer
currenty supported only 2d pooing (also on 3d input)
*/
class Pooling : public Layer {
public:
Pooling(Network *net, dataDim_t input_dim, int winH, int winW,
int strideH, int strideW, tkdnnPoolingMode_t pool_mode);
virtual ~Pooling();
virtual value_type* infer(dataDim_t &dim, value_type* srcData);
protected:
cudnnPoolingDescriptor_t poolingDesc;
int winH, winW;
int strideH, strideW;
tkdnnPoolingMode_t pool_mode;
value_type *dstData, *tmpInputData, *tmpOutputData; //where results will be putted
bool poolOn3d;
};
/**
Softmax layer
*/
class Softmax : public Layer {
public:
Softmax(Network *net, dataDim_t input_dim);
virtual ~Softmax();
virtual value_type* infer(dataDim_t &dim, value_type* srcData);
protected:
value_type *dstData; //where results will be putted
};
}
#endif //LAYER_H
-36
View File
@@ -1,36 +0,0 @@
#ifndef NETWORK_H
#define NETWORK_H
#include "utils.h"
namespace tkDNN {
struct dataDim_t;
class Layer;
const int MAX_LAYERS = 256;
class Network {
public:
Network();
virtual ~Network();
/**
Do inferece for every added layer
*/
value_type* infer(dataDim_t &dim, value_type* data);
bool addLayer(Layer *l);
cudnnDataType_t dataType;
cudnnTensorFormat_t tensorFormat;
cudnnHandle_t cudnnHandle;
cublasHandle_t cublasHandle;
private:
Layer* layers[MAX_LAYERS]; //contains layers of the net
int num_layers; //current number of layers
};
}
#endif //NETWORK_H
-3
View File
@@ -1,3 +0,0 @@
#include "utils.h"
void activationELUForward(value_type* srcData, value_type* dstData, int size);
+31
View File
@@ -0,0 +1,31 @@
#ifndef BOUNDINGBOX_H
#define BOUNDINGBOX_H
#include <iostream>
#include "tkdnn.h"
namespace tk { namespace dnn {
class BoundingBox : public tk::dnn::box
{
float overlap(const float p1, const float l1, const float p2, const float l22);
float boxesIntersection(const BoundingBox &b);
float boxesUnion(const BoundingBox &b);
public:
int uniqueTruthIndex = -1;
int truthFlag = 0;
float maxIoU = 0;
float IoU(const BoundingBox &b);
void clear();
friend std::ostream& operator<<(std::ostream& os, const BoundingBox& bb);
};
std::ostream& operator<<(std::ostream& os, const BoundingBox& bb);
bool boxComparison (const BoundingBox& a,const BoundingBox& b) ;
}}
#endif /*BOUNDINGBOX_H*/
+86
View File
@@ -0,0 +1,86 @@
#ifndef CENTERNETDETECTION_H
#define CENTERNETDETECTION_H
#include "kernels.h"
#include <opencv2/videoio.hpp>
#include "opencv2/opencv.hpp"
#include <time.h>
#include <vector>
#include <numeric> // std::iota
#include <algorithm> // std::sort
#include "DetectionNN.h"
#include "kernelsThrust.h"
namespace tk { namespace dnn {
class CenternetDetection : public DetectionNN
{
private:
tk::dnn::dataDim_t dim;
tk::dnn::dataDim_t dim2;
tk::dnn::dataDim_t dim_hm;
tk::dnn::dataDim_t dim_wh;
tk::dnn::dataDim_t dim_reg;
float *topk_scores;
int *topk_inds_;
float *topk_ys_;
float *topk_xs_;
int *ids_d, *ids_, *ids_2, *ids_2d;
float *scores, *scores_d;
int *clses, *clses_d;
int *topk_inds_d;
float *topk_ys_d;
float *topk_xs_d;
int *inttopk_xs_d, *inttopk_ys_d;
float *bbx0, *bby0, *bbx1, *bby1;
float *bbx0_d, *bby0_d, *bbx1_d, *bby1_d;
float *target_coords;
#ifdef OPENCV_CUDACONTRIB
float *mean_d;
float *stddev_d;
#else
cv::Vec<float, 3> mean;
cv::Vec<float, 3> stddev;
dnnType *input;
#endif
float *d_ptrs;
cv::Mat src;
cv::Mat dst;
cv::Mat dst2;
cv::Mat trans, trans2;
//processing
float toll = 0.000001;
int K = 100;
int width = 128;//56; // TODO
// pointer used in the kernels
float *src_out;
int *ids_out;
struct threshold op;
public:
CenternetDetection() {};
~CenternetDetection() {};
bool init(const std::string& tensor_path, const int n_classes=80, const int n_batches=1);
void preprocess(cv::Mat &frame, const int bi=0);
void postprocess(const int bi=0,const bool mAP=false);
};
} // namespace dnn
} // namespace tk
#endif /*CENTERNETDETECTION_H*/
+48
View File
@@ -0,0 +1,48 @@
#pragma once
#include <iostream>
#include "tkDNN/tkdnn.h"
namespace tk { namespace dnn {
struct darknetFields_t{
std::string type = "";
int width = 0;
int height = 0;
int channels = 3;
int batch_normalize=0;
int groups = 1;
int group_id = 0;
int filters=1;
int size_x=1;
int size_y=1;
int stride_x=1;
int stride_y=1;
int padding_x = 0;
int padding_y = 0;
int n_mask = 0;
int classes = 20;
int num = 1;
int pad = 0;
int coords = 4;
float scale_xy = 1;
std::vector<int> layers;
std::string activation = "linear";
friend std::ostream& operator<<(std::ostream& os, const darknetFields_t& f){
os << f.width << " " << f.height << " " << f.channels << " " << f.batch_normalize<< " " << f.filters << " " << f.activation<< " " << f.scale_xy;
return os;
}
};
std::string darknetParseType(const std::string& line);
bool divideNameAndValue(const std::string& line, std::string&name, std::string& value);
std::vector<int> fromStringToIntVec(const std::string& line, const char delimiter);
bool darknetParseFields(const std::string& line, darknetFields_t& fields);
tk::dnn::Network *darknetAddNet(darknetFields_t &fields);
void darknetAddLayer(tk::dnn::Network *net, darknetFields_t &f, std::string wgs_path,
std::vector<tk::dnn::Layer*> &netLayers, const std::vector<std::string>& names);
std::vector<std::string> darknetReadNames(const std::string& names_file);
tk::dnn::Network* darknetParser(const std::string& cfg_file, const std::string& wgs_path, const std::string& names_file);
}}
+183
View File
@@ -0,0 +1,183 @@
#ifndef DETECTIONNN_H
#define DETECTIONNN_H
#include <iostream>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <mutex>
#include "utils.h"
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include "tkdnn.h"
// #define OPENCV_CUDACONTRIB //if OPENCV has been compiled with CUDA and contrib.
#ifdef OPENCV_CUDACONTRIB
#include <opencv2/cudawarping.hpp>
#include <opencv2/cudaarithm.hpp>
#endif
namespace tk { namespace dnn {
class DetectionNN {
protected:
tk::dnn::NetworkRT *netRT = nullptr;
dnnType *input_d;
std::vector<cv::Size> originalSize;
cv::Scalar colors[256];
int nBatches = 1;
#ifdef OPENCV_CUDACONTRIB
cv::cuda::GpuMat bgr[3];
cv::cuda::GpuMat imagePreproc;
#else
cv::Mat bgr[3];
cv::Mat imagePreproc;
dnnType *input;
#endif
/**
* This method preprocess the image, before feeding it to the NN.
*
* @param frame original frame to adapt for inference.
* @param bi batch index
*/
virtual void preprocess(cv::Mat &frame, const int bi=0) = 0;
/**
* This method postprocess the output of the NN to obtain the correct
* boundig boxes.
*
* @param bi batch index
* @param mAP set to true only if all the probabilities for a bounding
* box are needed, as in some cases for the mAP calculation
*/
virtual void postprocess(const int bi=0,const bool mAP=false) = 0;
public:
int classes = 0;
float confThreshold = 0.3; /*threshold on the confidence of the boxes*/
std::vector<tk::dnn::box> detected; /*bounding boxes in output*/
std::vector<std::vector<tk::dnn::box>> batchDetected; /*bounding boxes in output*/
std::vector<double> stats; /*keeps track of inference times (ms)*/
std::vector<std::string> classesNames;
DetectionNN() {};
~DetectionNN(){};
/**
* Method used to inialize the class, allocate memory and compute
* needed data.
*
* @param tensor_path path to the rt file og the NN.
* @param n_classes number of classes for the given dataset.
* @param n_batches maximum number of batches to use in inference
* @return true if everything is correct, false otherwise.
*/
virtual bool init(const std::string& tensor_path, const int n_classes=80, const int n_batches=1) = 0;
/**
* This method performs the whole detection of the NN.
*
* @param frames frames to run detection on.
* @param cur_batches number of batches to use in inference
* @param save_times if set to true, preprocess, inference and postprocess times
* are saved on a csv file, otherwise not.
* @param times pointer to the output stream where to write times
* @param mAP set to true only if all the probabilities for a bounding
* box are needed, as in some cases for the mAP calculation
*/
void update(std::vector<cv::Mat>& frames, const int cur_batches=1, bool save_times=false, std::ofstream *times=nullptr, const bool mAP=false){
if(save_times && times==nullptr)
FatalError("save_times set to true, but no valid ofstream given");
if(cur_batches > nBatches)
FatalError("A batch size greater than nBatches cannot be used");
originalSize.clear();
if(TKDNN_VERBOSE) printCenteredTitle(" TENSORRT detection ", '=', 30);
{
TKDNN_TSTART
for(int bi=0; bi<cur_batches;++bi){
if(!frames[bi].data)
FatalError("No image data feed to detection");
originalSize.push_back(frames[bi].size());
preprocess(frames[bi], bi);
}
TKDNN_TSTOP
if(save_times) *times<<t_ns<<";";
}
//do inference
tk::dnn::dataDim_t dim = netRT->input_dim;
dim.n = cur_batches;
{
if(TKDNN_VERBOSE) dim.print();
TKDNN_TSTART
netRT->infer(dim, input_d);
TKDNN_TSTOP
if(TKDNN_VERBOSE) dim.print();
stats.push_back(t_ns);
if(save_times) *times<<t_ns<<";";
}
batchDetected.clear();
{
TKDNN_TSTART
for(int bi=0; bi<cur_batches;++bi)
postprocess(bi, mAP);
TKDNN_TSTOP
if(save_times) *times<<t_ns<<"\n";
}
}
/**
* Method to draw boundixg boxes and labels on a frame.
*
* @param frames orginal frame to draw bounding box on.
*/
void draw(std::vector<cv::Mat>& frames) {
tk::dnn::box b;
int x0, w, x1, y0, h, y1;
int objClass;
std::string det_class;
int baseline = 0;
float font_scale = 0.5;
int thickness = 2;
for(int bi=0; bi<frames.size(); ++bi){
// draw dets
for(int i=0; i<batchDetected[bi].size(); i++) {
b = batchDetected[bi][i];
x0 = b.x;
x1 = b.x + b.w;
y0 = b.y;
y1 = b.y + b.h;
det_class = classesNames[b.cl];
// draw rectangle
cv::rectangle(frames[bi], cv::Point(x0, y0), cv::Point(x1, y1), colors[b.cl], 2);
// draw label
cv::Size text_size = getTextSize(det_class, cv::FONT_HERSHEY_SIMPLEX, font_scale, thickness, &baseline);
cv::rectangle(frames[bi], cv::Point(x0, y0), cv::Point((x0 + text_size.width - 2), (y0 - text_size.height - 2)), colors[b.cl], -1);
cv::putText(frames[bi], det_class, cv::Point(x0, (y0 - (baseline / 2))), cv::FONT_HERSHEY_SIMPLEX, font_scale, cv::Scalar(255, 255, 255), thickness);
}
}
}
};
}}
#endif /* DETECTIONNN_H*/
+161
View File
@@ -0,0 +1,161 @@
#include <iostream>
#include <signal.h>
#include <stdlib.h> /* srand, rand */
#include <unistd.h>
#include <mutex>
#include <Eigen/Dense>
#include "utils.h"
#include "tkdnn.h"
namespace tk { namespace dnn {
/**
*
* @author Francesco Gatti
*/
class ImuOdom {
public:
tk::dnn::Network *net = nullptr;
// Network input dim
tk::dnn::dataDim_t dim0;
tk::dnn::dataDim_t dim1;
tk::dnn::dataDim_t dim2;
// Network output dim
tk::dnn::dataDim_t odim0;
tk::dnn::dataDim_t odim1;
// input pointers
dnnType *i0_d, *i1_d, *i2_d;
// output pointers
dnnType *o0_d, *o1_d;
// output eigen CPU
Eigen::MatrixXf deltaP, deltaQ;
Eigen::MatrixXd odomPOS, odomEULER;
Eigen::Matrix3d odomROT;
Eigen::Isometry3f tf = Eigen::Isometry3f::Identity();
ImuOdom() {}
virtual ~ImuOdom() {}
/**
* Method used for inizialize the class
*
* @return Success of the initialization
*/
bool init(std::string layers_path) {
dim0 = tk::dnn::dataDim_t(1, 4, 1, 100);
dim1 = tk::dnn::dataDim_t(1, 3, 1, 100);
dim2 = tk::dnn::dataDim_t(1, 3, 1, 100);
checkCuda( cudaMalloc(&i0_d, dim0.tot()*sizeof(dnnType)) );
checkCuda( cudaMalloc(&i1_d, dim1.tot()*sizeof(dnnType)) );
checkCuda( cudaMalloc(&i2_d, dim2.tot()*sizeof(dnnType)) );
std::string c0_bin = layers_path + "/conv1d_7.bin";
std::string c1_bin = layers_path + "/conv1d_8.bin";
std::string c2_bin = layers_path + "/conv1d_9.bin";
std::string c3_bin = layers_path + "/conv1d_10.bin";
std::string c4_bin = layers_path + "/conv1d_11.bin";
std::string c5_bin = layers_path + "/conv1d_12.bin";
std::string l0_bin = layers_path + "/bidirectional_3.bin";
std::string l1_bin = layers_path + "/bidirectional_4.bin";
std::string d0_bin = layers_path + "/dense_3.bin";
std::string d1_bin = layers_path + "/dense_4.bin";
net = new tk::dnn::Network(dim0);
tk::dnn::Input *x0 = new tk::dnn::Input (net, dim0, i0_d);
tk::dnn::Conv2d *x0_0 = new tk::dnn::Conv2d (net, 128, 1, 11, 1, 1, 0, 0, c0_bin);
tk::dnn::Conv2d *x0_1 = new tk::dnn::Conv2d (net, 128, 1, 11, 1, 1, 0, 0, c1_bin);
tk::dnn::Pooling *x0_2 = new tk::dnn::Pooling(net, 1, 3, 1, 3 ,0, 0, tk::dnn::tkdnnPoolingMode_t::POOLING_MAX);
tk::dnn::Input *x1 = new tk::dnn::Input (net, dim1, i1_d);
tk::dnn::Conv2d *x1_0 = new tk::dnn::Conv2d (net, 128, 1, 11, 1, 1, 0, 0, c2_bin);
tk::dnn::Conv2d *x1_1 = new tk::dnn::Conv2d (net, 128, 1, 11, 1, 1, 0, 0, c3_bin);
tk::dnn::Pooling *x1_2 = new tk::dnn::Pooling(net, 1, 3, 1, 3, 0, 0, tk::dnn::tkdnnPoolingMode_t::POOLING_MAX);
tk::dnn::Input *x2 = new tk::dnn::Input (net, dim2, i2_d);
tk::dnn::Conv2d *x2_0 = new tk::dnn::Conv2d (net, 128, 1, 11, 1, 1, 0, 0, c4_bin);
tk::dnn::Conv2d *x2_1 = new tk::dnn::Conv2d (net, 128, 1, 11, 1, 1, 0, 0, c5_bin);
tk::dnn::Pooling *x2_2 = new tk::dnn::Pooling(net, 1, 3, 1, 3, 0, 0, tk::dnn::tkdnnPoolingMode_t::POOLING_MAX);
tk::dnn::Layer *concat_l[3] = { x0_2, x1_2, x2_2 };
tk::dnn::Route *concat = new tk::dnn::Route(net, concat_l, 3);
tk::dnn::LSTM *lstm0 = new tk::dnn::LSTM(net, 128, true, l0_bin);
tk::dnn::LSTM *lstm1 = new tk::dnn::LSTM(net, 128, false, l1_bin);
tk::dnn::Dense *d0 = new tk::dnn::Dense(net, 3, d0_bin);
tk::dnn::Layer *lstm1_l[1] = { lstm1 };
tk::dnn::Route *lstm1_link = new tk::dnn::Route(net, lstm1_l, 1);
tk::dnn::Dense *d1 = new tk::dnn::Dense(net, 4, d1_bin);
net->print();
// output data
o0_d = d0->dstData;
o1_d = d1->dstData;
odim0 = d0->output_dim;
odim1 = d1->output_dim;
deltaP.resize(odim0.tot(), 1);
deltaQ.resize(odim1.tot(), 1);
odomPOS = Eigen::MatrixXd::Zero(3, 1);
odomROT = Eigen::MatrixXd::Identity(3, 3);
odomEULER = Eigen::MatrixXd::Zero(3, 1);
return true;
}
void close() {
// TODO: dealloc :)
}
void update(dnnType *x0, dnnType *x1, dnnType *x2) {
checkCuda( cudaMemcpy(i0_d, x0, dim0.tot()*sizeof(dnnType), cudaMemcpyHostToDevice) );
checkCuda( cudaMemcpy(i1_d, x1, dim1.tot()*sizeof(dnnType), cudaMemcpyHostToDevice) );
checkCuda( cudaMemcpy(i2_d, x2, dim2.tot()*sizeof(dnnType), cudaMemcpyHostToDevice) );
// Inference
tk::dnn::dataDim_t dim;
net->infer(dim, nullptr);
checkCuda( cudaMemcpy(deltaP.data(), o0_d, odim0.tot()*sizeof(dnnType), cudaMemcpyDeviceToHost) );
checkCuda( cudaMemcpy(deltaQ.data(), o1_d, odim1.tot()*sizeof(dnnType), cudaMemcpyDeviceToHost) );
// compute odom
Eigen::Quaterniond q;
q.w() = deltaQ(0);
q.x() = deltaQ(1);
q.y() = deltaQ(2);
q.z() = deltaQ(3);
odomPOS = odomPOS + odomROT*deltaP.cast<double>(); // V1
//odomPOS = odomPOS + deltaP.cast<double>(); // V2
odomROT = odomROT * q.normalized().toRotationMatrix();
// compute euler
auto newEULER = odomROT.eulerAngles(0, 1, 2);
for(int i=0; i<3; i++) {
while( fabs(newEULER(i) - odomEULER(i)) > M_PI_2 ) {
newEULER(i) += newEULER(i) - odomEULER(i) > 0 ? -M_PI : +M_PI;
//std::cout<<newEULER(i)<<" "<<odomEULER(i)<<"\n";
}
}
odomEULER = newEULER;
// compose tf
tf.matrix().block(0, 0, 3, 3) = odomROT.cast<float>();
tf.matrix().block(0, 3, 3, 1) = odomPOS.cast<float>();
}
};
}}
+69
View File
@@ -0,0 +1,69 @@
#ifndef INT8BATCHSTREAM_H
#define INT8BATCHSTREAM_H
#include <vector>
#include <assert.h>
#include <algorithm>
#include <iterator>
#include <stdint.h>
#include <iostream>
#include <string>
#include <fstream>
#include <iomanip>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <mutex>
#include "NvInfer.h"
#include "utils.h"
#include "tkdnn.h"
/*
* BatchStream implements the stream for the INT8 calibrator.
* It reads the two files .txt with the list of image file names
* and the list of label file names.
* It then iterates on images and labels.
*/
class BatchStream {
public:
BatchStream(tk::dnn::dataDim_t dim, int batchSize, int maxBatches, const std::string& fileimglist, const std::string& filelabellist);
virtual ~BatchStream() { }
void reset(int firstBatch);
bool next();
void skip(int skipCount);
float *getBatch() { return mBatch.data(); }
float *getLabels() { return mLabels.data(); }
int getBatchesRead() const { return mBatchCount; }
int getBatchSize() const { return mBatchSize; }
nvinfer1::DimsNCHW getDims() const { return mDims; }
float* getFileBatch() { return &mFileBatch[0]; }
float* getFileLabels() { return &mFileLabels[0]; }
void readInListFile(const std::string& dataFilePath, std::vector<std::string>& mListIn);
void readCVimage(std::string inputFileName, std::vector<float>& res, bool fixshape = true);
void readLabels(std::string inputFileName ,std::vector<float>& ris);
bool update();
private:
int mBatchSize{ 0 };
int mMaxBatches{ 0 };
int mBatchCount{ 0 };
int mFileCount{ 0 };
int mFileBatchPos{ 0 };
int mImageSize{ 0 };
nvinfer1::DimsNCHW mDims;
std::vector<float> mBatch;
std::vector<float> mLabels;
std::vector<float> mFileBatch;
std::vector<float> mFileLabels;
int mHeight;
int mWidth;
std::string mFileImgList;
std::vector<std::string> mListImg;
std::string mFileLabelList;
std::vector<std::string> mListLabel;
};
#endif //INT8BATCHSTREAM
+49
View File
@@ -0,0 +1,49 @@
#ifndef INT8CALIBRATOR_H
#define INT8CALIBRATOR_H
#include <vector>
#include <assert.h>
#include <algorithm>
#include <iterator>
#include <stdint.h>
#include <iostream>
#include <string>
#include "NvInfer.h"
#include <fstream>
#include <iomanip>
#include "Int8BatchStream.h"
#include "tkdnn.h"
#include "utils.h"
/*
* Int8EntropyCalibrator implements the INT8 calibrator to achieve the
* INT8 quantization. It uses a BatchStream stream to scroll through
* images data. It also implements the calibration cache, a way to
* save the calibration process results to reduce the running time:
* the calibration process takes a long time.
*/
class Int8EntropyCalibrator : public nvinfer1::IInt8EntropyCalibrator {
public:
Int8EntropyCalibrator(BatchStream& stream, int firstBatch, const std::string& calibTableFilePath,
const std::string& inputBlobName, bool readCache = true);
virtual ~Int8EntropyCalibrator() { checkCuda(cudaFree(mDeviceInput)); }
int getBatchSize() const override { return mStream.getBatchSize(); }
bool getBatch(void* bindings[], const char* names[], int nbBindings) override;
const void* readCalibrationCache(size_t& length) override;
void writeCalibrationCache(const void* cache, size_t length) override;
private:
BatchStream mStream;
const std::string mCalibTableFilePath{ nullptr };
const std::string mInputBlobName;
bool mReadCache{ true };
size_t mInputCount;
void* mDeviceInput{ nullptr };
std::vector<char> mCalibrationCache;
};
#endif //INT8CALIBRATOR_H
+679
View File
@@ -0,0 +1,679 @@
#ifndef LAYER_H
#define LAYER_H
#include<iostream>
#include<vector>
#include "utils.h"
#include "Network.h"
namespace tk { namespace dnn {
enum layerType_t {
LAYER_INPUT,
LAYER_DENSE,
LAYER_CONV2D,
LAYER_DECONV2D,
LAYER_DEFORMCONV2D,
LAYER_LSTM,
LAYER_ACTIVATION,
LAYER_ACTIVATION_CRELU,
LAYER_ACTIVATION_LEAKY,
LAYER_ACTIVATION_MISH,
LAYER_FLATTEN,
LAYER_RESHAPE,
LAYER_MULADD,
LAYER_POOLING,
LAYER_SOFTMAX,
LAYER_ROUTE,
LAYER_REORG,
LAYER_SHORTCUT,
LAYER_UPSAMPLE,
LAYER_REGION,
LAYER_YOLO
};
#define TKDNN_BN_MIN_EPSILON 1e-5
/**
Simple layer Father class
*/
class Layer {
public:
Layer(Network *net);
virtual ~Layer();
virtual layerType_t getLayerType() = 0;
virtual dnnType* infer(dataDim_t &dim, dnnType* srcData) {
std::cout<<"No infer action for this layer\n";
return NULL;
}
void setFinal() { this->final = true; }
dataDim_t input_dim, output_dim;
dnnType *dstData = nullptr; //where results will be putted
int id = 0;
bool final; //if the layer is the final one
std::string getLayerName() {
layerType_t type = getLayerType();
switch(type) {
case LAYER_INPUT: return "Input";
case LAYER_DENSE: return "Dense";
case LAYER_CONV2D: return "Conv2d";
case LAYER_DECONV2D: return "DeConv2d";
case LAYER_DEFORMCONV2D: return "DeformConv2d";
case LAYER_LSTM: return "LSTM";
case LAYER_ACTIVATION: return "Activation";
case LAYER_ACTIVATION_CRELU: return "ActivationCReLU";
case LAYER_ACTIVATION_LEAKY: return "ActivationLeaky";
case LAYER_ACTIVATION_MISH: return "ActivationMish";
case LAYER_FLATTEN: return "Flatten";
case LAYER_RESHAPE: return "Reshape";
case LAYER_MULADD: return "MulAdd";
case LAYER_POOLING: return "Pooling";
case LAYER_SOFTMAX: return "Softmax";
case LAYER_ROUTE: return "Route";
case LAYER_REORG: return "Reorg";
case LAYER_SHORTCUT: return "Shortcut";
case LAYER_UPSAMPLE: return "Upsample";
case LAYER_REGION: return "Region";
case LAYER_YOLO: return "Yolo";
default: return "unknown";
}
}
protected:
Network *net;
cudnnTensorDescriptor_t srcTensorDesc, dstTensorDesc;
};
/**
Father class of all layer that need to load trained weights
*/
class LayerWgs : public Layer {
public:
LayerWgs(Network *net, int inputs, int outputs, int kh, int kw, int kt,
std::string fname_weights, bool batchnorm = false, bool additional_bias = false, bool deConv = false, int groups = 1);
virtual ~LayerWgs();
int inputs, outputs;
std::string weights_path;
dnnType *data_h, *data_d;
dnnType *bias_h, *bias_d;
// additional bias for DCN
bool additional_bias;
dnnType *bias2_h = nullptr, *bias2_d = nullptr;
//batchnorm
bool batchnorm;
dnnType *power_h = nullptr;
dnnType *scales_h = nullptr, *scales_d = nullptr;
dnnType *mean_h = nullptr, *mean_d = nullptr;
dnnType *variance_h = nullptr, *variance_d = nullptr;
//fp16
__half *data16_h = nullptr, *bias16_h = nullptr;
__half *data16_d = nullptr, *bias16_d = nullptr;
__half *bias216_h = nullptr, *bias216_d = nullptr;
__half *power16_h = nullptr, *power16_d = nullptr;
__half *scales16_h = nullptr, *scales16_d = nullptr;
__half *mean16_h = nullptr, *mean16_d = nullptr;
__half *variance16_h = nullptr, *variance16_d = nullptr;
void releaseHost(bool release32 = true, bool release16 = true) {
if(release32) {
if( data_h != nullptr) { delete [] data_h; data_h = nullptr; }
if( bias_h != nullptr) { delete [] bias_h; bias_h = nullptr; }
if( bias2_h != nullptr) { delete [] bias2_h; bias2_h = nullptr; }
if( scales_h != nullptr) { delete [] scales_h; scales_h = nullptr; }
if( mean_h != nullptr) { delete [] mean_h; mean_h = nullptr; }
if(variance_h != nullptr) { delete [] variance_h; variance_h = nullptr; }
if( power_h != nullptr) { delete [] power_h; power_h = nullptr; }
}
if(net->fp16 && release16) {
if( data16_h != nullptr) { delete [] data16_h; data16_h = nullptr; }
if( bias16_h != nullptr) { delete [] bias16_h; bias16_h = nullptr; }
if( bias216_h != nullptr) { delete [] bias216_h; bias216_h = nullptr; }
if( scales16_h != nullptr) { delete [] scales16_h; scales16_h = nullptr; }
if( mean16_h != nullptr) { delete [] mean16_h; mean16_h = nullptr; }
if(variance16_h != nullptr) { delete [] variance16_h; variance16_h = nullptr; }
if( power16_h != nullptr) { delete [] power16_h; power16_h = nullptr; }
}
}
void releaseDevice(bool release32 = true, bool release16 = true) {
if(release32) {
if( data_d != nullptr) { cudaFree( data_d); data_d = nullptr; }
if( bias_d != nullptr) { cudaFree( bias_d); bias_d = nullptr; }
if( bias2_d != nullptr) { cudaFree( bias2_d); bias2_d = nullptr; }
if( scales_d != nullptr) { cudaFree( scales_d); scales_d = nullptr; }
if( mean_d != nullptr) { cudaFree( mean_d); mean_d = nullptr; }
if(variance_d != nullptr) { cudaFree(variance_d); variance_d = nullptr; }
}
if(net->fp16 && release16) {
if( data16_d != nullptr) { cudaFree( data16_d); data16_d = nullptr; }
if( bias16_d != nullptr) { cudaFree( bias16_d); bias16_d = nullptr; }
if( bias216_d != nullptr) { cudaFree( bias216_d); bias216_d = nullptr; }
if( scales16_d != nullptr) { cudaFree( scales16_d); scales16_d = nullptr; }
if( mean16_d != nullptr) { cudaFree( mean16_d); mean16_d = nullptr; }
if(variance16_d != nullptr) { cudaFree(variance16_d); variance16_d = nullptr; }
if( power16_d != nullptr) { cudaFree( power16_d); power16_d = nullptr; }
}
}
};
/**
Input layer (it doesnt need weigths)
*/
class Input : public Layer {
public:
Input(Network *net, dataDim_t &dim, dnnType* srcData) : Layer(net) {
input_dim = dim;
output_dim = dim;
dstData = srcData;
}
virtual ~Input() {}
virtual layerType_t getLayerType() { return LAYER_INPUT; };
virtual dnnType* infer(dataDim_t &dim, dnnType* srcData) {
dim = output_dim;
return dstData;
}
};
/**
Dense (full interconnection) layer
*/
class Dense : public LayerWgs {
public:
Dense(Network *net, int out_ch, std::string fname_weights);
virtual ~Dense();
virtual layerType_t getLayerType() { return LAYER_DENSE; };
virtual dnnType* infer(dataDim_t &dim, dnnType* srcData);
};
/**
Avaible activation functions
*/
typedef enum {
ACTIVATION_ELU = 100,
ACTIVATION_LEAKY = 101,
ACTIVATION_MISH = 102
} tkdnnActivationMode_t;
/**
Activation layer (it doesnt need weigths)
*/
class Activation : public Layer {
public:
int act_mode;
float ceiling;
Activation(Network *net, int act_mode, const float ceiling=0.0);
virtual ~Activation();
virtual layerType_t getLayerType() {
if(act_mode == CUDNN_ACTIVATION_CLIPPED_RELU)
return LAYER_ACTIVATION_CRELU;
else if (act_mode == ACTIVATION_LEAKY)
return LAYER_ACTIVATION_LEAKY;
else if (act_mode == ACTIVATION_MISH)
return LAYER_ACTIVATION_MISH;
else
return LAYER_ACTIVATION;
};
virtual dnnType* infer(dataDim_t &dim, dnnType* srcData);
protected:
cudnnActivationDescriptor_t activDesc;
};
/**
Convolutional 2D layer
WEIGHTS shape: OUTCH, INCH, KH, KW ...
BIAS shape: OUTCH
with BATCHNORM:
scales: OUTCH
means: OUTCH
variance: OUTCH
*/
class Conv2d : public LayerWgs {
public:
Conv2d( Network *net, int out_ch, int kernelH, int kernelW,
int strideH, int strideW, int paddingH, int paddingW,
std::string fname_weights, bool batchnorm = false, bool deConv = false, int groups = 1, bool additional_bias=false);
virtual ~Conv2d();
virtual layerType_t getLayerType() { return LAYER_CONV2D; };
virtual dnnType* infer(dataDim_t &dim, dnnType* srcData);
int kernelH, kernelW, strideH, strideW, paddingH, paddingW;
bool deConv, additional_bias;
int groups;
protected:
cudnnFilterDescriptor_t filterDesc;
cudnnConvolutionDescriptor_t convDesc;
cudnnConvolutionFwdAlgoPerf_t algo;
cudnnConvolutionBwdDataAlgoPerf_t bwAlgo;
cudnnTensorDescriptor_t biasTensorDesc;
void initCUDNN(bool back = false);
void inferCUDNN(dnnType* srcData, bool back = false);
void* workSpace;
size_t ws_sizeInBytes;
};
/**
Bidirectional LSTM layer
ONLY BIDIRECTIONAL (TODO: more configurable)
currently implemented as 2 inferences: forward and backward (TODO: only 1 cudnn inference)
implementation info:
https://github.com/jiangnanhugo/seq2seq_cuda/blob/e4dbdcfa0517c972bfd4beea9f11a5233954093c/src/rnn.cpp
https://github.com/Jeffery-Song/mxnet-test/blob/aab666faad44011f7a67b527b5f6c960367d0422/src/operator/cudnn_rnn-inl.h
https://stackoverflow.com/a/38737941
https://colah.github.io/posts/2015-08-Understanding-LSTMs/
PARAMS (numlayers*2):
layer0:
( INCH, ? ) ???
( HIDDEN, ? ) ???
( HIDDEN * 8 ) ???
layer2:
( INCH, ? ) ???
( HIDDEN, ? ) ???
( HIDDEN * 8 ) ???
OUTPUT shape:
(N, C, 1, W) ---> LSTM(HIDDEN, returnSeq=True) ---> (N, 2*HIDDEN, 1, W) # W is seqLength
(N, C, 1, W) ---> LSTM(HIDDEN, returnSeq=False) ---> (N, 2*HIDDEN, 1, 1)
*/
class LSTM : public Layer {
public:
LSTM(Network *net, int hiddensize, bool returnSeq, std::string fname_weights);
virtual ~LSTM();
virtual layerType_t getLayerType() { return LAYER_LSTM; };
virtual dnnType* infer(dataDim_t &dim, dnnType* srcData);
const bool bidirectional = true; /**> is the net bidir */
bool returnSeq = false; /**> if false return only the result of last timestep */
int stateSize = 0; /**> number of hidden states */
int seqLen = 0; /**> number of timesteps */
int numLayers = 1; /**> number of internal layers */
protected:
cudnnRNNDescriptor_t rnnDesc;
cudnnDropoutDescriptor_t dropoutDesc;
dnnType *dropout_states_, *work_space_;
size_t workspace_byte_, dropout_byte_;
int workspace_size_, dropout_size_;
std::vector<cudnnTensorDescriptor_t> x_desc_vec_, y_desc_vec_;
cudnnTensorDescriptor_t hx_desc_, cx_desc_;
cudnnTensorDescriptor_t hy_desc_, cy_desc_;
dnnType *hx_ptr, *cx_ptr, *hy_ptr, *cy_ptr;
int stateDataDim;
cudnnFilterDescriptor_t w_desc_;
dnnType *w_ptr;
dnnType *w_h;
dnnType *wf_ptr, *wb_ptr; // params pointer forward and backward layer
// used during inference
dataDim_t one_output_dim; // output dim of as single inference
dnnType *srcF, *srcB; // input of single inference
dnnType *dstF, *dstB_NR, *dstB; // output of single inference, dstB_NR = dstB not reversed
};
/**
Convolutional 2D layer
*/
class DeConv2d : public Conv2d {
public:
DeConv2d( Network *net, int out_ch, int kernelH, int kernelW,
int strideH, int strideW, int paddingH, int paddingW,
std::string fname_weights, bool batchnorm = false, int groups = 1) :
Conv2d(net, out_ch, kernelH, kernelW, strideH, strideW, paddingH, paddingW, fname_weights, batchnorm, true, groups) {}
virtual ~DeConv2d() {}
virtual layerType_t getLayerType() { return LAYER_DECONV2D; };
virtual dnnType* infer(dataDim_t &dim, dnnType* srcData);
};
/**
Deformable Convolutionl 2d layer
*/
class DeformConv2d : public LayerWgs {
public:
DeformConv2d( Network *net, int out_ch, int deformable_group, int kernelH, int kernelW,
int strideH, int strideW, int paddingH, int paddingW,
std::string d_fname_weights, std::string fname_weights, bool batchnorm);
virtual ~DeformConv2d();
virtual layerType_t getLayerType() { return LAYER_DEFORMCONV2D; };
virtual dnnType* infer(dataDim_t &dim, dnnType* srcData);
tk::dnn::Conv2d *preconv;
int out_ch;
int deformableGroup;
int kernelH, kernelW, strideH, strideW, paddingH, paddingW;
dnnType *ones_d1;
dnnType *ones_d2;
int chunk_dim;
dnnType *offset, *mask;
dnnType *output_conv;
cublasStatus_t stat;
cublasHandle_t handle;
protected:
cudnnTensorDescriptor_t biasTensorDesc;
void initCUDNN();
};
/**
Flatten layer
is actually a matrix transposition
*/
class Flatten : public Layer {
public:
Flatten(Network *net);
virtual ~Flatten();
virtual layerType_t getLayerType() { return LAYER_FLATTEN; };
virtual dnnType* infer(dataDim_t &dim, dnnType* srcData);
};
/**
Reshape layer
*/
class Reshape : public Layer {
public:
Reshape(Network *net, dataDim_t new_dim);
virtual ~Reshape();
virtual layerType_t getLayerType() { return LAYER_RESHAPE; };
virtual dnnType* infer(dataDim_t &dim, dnnType* srcData);
};
/**
MulAdd layer
apply a multiplication and then an addition for each data
*/
class MulAdd : public Layer {
public:
MulAdd(Network *net, dnnType mul, dnnType add);
virtual ~MulAdd();
virtual layerType_t getLayerType() { return LAYER_MULADD; };
virtual dnnType* infer(dataDim_t &dim, dnnType* srcData);
protected:
dnnType mul, add;
dnnType *add_vector;
};
/**
Avaible pooling functions (padding on tkDNN is not supported)
*/
typedef enum {
POOLING_MAX = 0,
POOLING_AVERAGE = 1, // count for average includes padded values
POOLING_AVERAGE_EXCLUDE_PADDING = 2, // count for average does not include padded values
POOLING_MAX_FIXEDSIZE = 100 // max pool darknet fashion
} tkdnnPoolingMode_t;
/**
Pooling layer
currenty supported only 2d pooing (also on 3d input)
*/
class Pooling : public Layer {
public:
int winH, winW;
int strideH, strideW;
int paddingH, paddingW;
bool size;
tkdnnPoolingMode_t pool_mode;
Pooling(Network *net, int winH, int winW,
int strideH, int strideW,
int paddingH, int paddingW,
tkdnnPoolingMode_t pool_mode);
virtual ~Pooling();
virtual layerType_t getLayerType() { return LAYER_POOLING; };
virtual dnnType* infer(dataDim_t &dim, dnnType* srcData);
protected:
cudnnPoolingDescriptor_t poolingDesc;
dnnType *tmpInputData, *tmpOutputData;
bool poolOn3d;
};
/**
Softmax layer
*/
class Softmax : public Layer {
public:
Softmax(Network *net, const tk::dnn::dataDim_t* dim=nullptr, const cudnnSoftmaxMode_t mode=CUDNN_SOFTMAX_MODE_CHANNEL);
virtual ~Softmax();
virtual layerType_t getLayerType() { return LAYER_SOFTMAX; };
virtual dnnType* infer(dataDim_t &dim, dnnType* srcData);
dataDim_t dim;
cudnnSoftmaxMode_t mode;
};
/**
Route layer
Merge a list of layers
*/
class Route : public Layer {
public:
Route(Network *net, Layer **layers, int layers_n, int groups = 1, int group_id = 0);
virtual ~Route();
virtual layerType_t getLayerType() { return LAYER_ROUTE; };
virtual dnnType* infer(dataDim_t &dim, dnnType* srcData);
public:
static const int MAX_LAYERS = 32;
Layer *layers[MAX_LAYERS]; //ids of layers to be merged
int layers_n; //number of layers
int groups;
int group_id;
};
/**
Reorg layer
Mantain same dimension but change C*H*W distribution
*/
class Reorg : public Layer {
public:
Reorg(Network *net, int stride);
virtual ~Reorg();
virtual layerType_t getLayerType() { return LAYER_REORG; };
virtual dnnType* infer(dataDim_t &dim, dnnType* srcData);
int stride;
};
/**
Shortcut layer
sum with stride another layer
*/
class Shortcut : public Layer {
public:
Shortcut(Network *net, Layer *backLayer);
virtual ~Shortcut();
virtual layerType_t getLayerType() { return LAYER_SHORTCUT; };
virtual dnnType* infer(dataDim_t &dim, dnnType* srcData);
public:
Layer *backLayer;
};
/**
Upsample layer
Mantain same dimension but change C*H*W distribution
*/
class Upsample : public Layer {
public:
Upsample(Network *net, int stride);
virtual ~Upsample();
virtual layerType_t getLayerType() { return LAYER_UPSAMPLE; };
virtual dnnType* infer(dataDim_t &dim, dnnType* srcData);
int stride;
bool reverse;
};
struct box {
int cl;
float x, y, w, h;
float prob;
std::vector<float> probs;
void print()
{
std::cout<<"x: "<<x<<"\ty: "<<y<<"\tw: "<<w<<"\th: "<<h<<"\tcl: "<<cl<<"\tprob: "<<prob<<std::endl;
}
};
struct sortable_bbox {
int index;
int cl;
float **probs;
};
/**
Yolo3 layer
*/
class Yolo : public Layer {
public:
struct box {
float x, y, w, h;
};
struct detection{
Yolo::box bbox;
int classes;
float *prob;
float *mask;
float objectness;
int sort_class;
};
Yolo(Network *net, int classes, int num, std::string fname_weights,int n_masks=3, float scale_xy=1);
virtual ~Yolo();
virtual layerType_t getLayerType() { return LAYER_YOLO; };
int classes, num, n_masks;
dnnType *mask_h, *mask_d; //anchors
dnnType *bias_h, *bias_d; //anchors
float scaleXY;
std::vector<std::string> classesNames;
virtual dnnType* infer(dataDim_t &dim, dnnType* srcData);
int computeDetections(Yolo::detection *dets, int &ndets, int netw, int neth, float thresh);
dnnType *predictions;
static const int MAX_DETECTIONS = 8192;
static Yolo::detection *allocateDetections(int nboxes, int classes);
static void mergeDetections(Yolo::detection *dets, int ndets, int classes);
};
/**
Region layer
*/
class Region : public Layer {
public:
Region(Network *net, int classes, int coords, int num);
virtual ~Region();
virtual layerType_t getLayerType() { return LAYER_REGION; };
int classes, coords, num;
virtual dnnType* infer(dataDim_t &dim, dnnType* srcData);
};
class RegionInterpret {
public:
RegionInterpret(dataDim_t input_dim, dataDim_t output_dim,
int classes, int coords, int num, float thresh, std::string fname_weights);
~RegionInterpret();
dataDim_t input_dim, output_dim;
dnnType *bias_h, *bias_d; //anchors
int classes, coords, num;
float thresh;
box *boxes;
float **probs;
sortable_bbox *s;
box res_boxes[256];
int res_boxes_n;
box get_region_box(float *x, float *biases, int n, int index, int i, int j, int w, int h, int stride);
void get_region_boxes( float *input, int w, int h, int netw, int neth, float thresh,
float **probs, box *boxes, int only_objectness,
int *map, float tree_thresh, int relative);
void correct_region_boxes(box *boxes, int n, int w, int h, int netw, int neth, int relative);
void interpretData(dnnType *data_h, int imageW = 0, int imageH = 0);
void showImageResult(dnnType *input_h);
static float box_iou(box a, box b);
};
}}
#endif //LAYER_H
+77
View File
@@ -0,0 +1,77 @@
#ifndef MOBILENETDETECTION_H
#define MOBILENETDETECTION_H
#include <opencv2/videoio.hpp>
#include "opencv2/opencv.hpp"
#include "DetectionNN.h"
#define N_COORDS 4
#define N_SSDSPEC 6
namespace tk { namespace dnn {
struct SSDSpec
{
int featureSize = 0;
int shrinkage = 0;
int boxWidth = 0;
int boxHeight = 0;
int ratio1 = 0;
int ratio2 = 0;
SSDSpec() {}
SSDSpec(int feature_size, int shrinkage, int box_width, int box_height, int ratio1, int ratio2) :
featureSize(feature_size), shrinkage(shrinkage), boxWidth(box_width),
boxHeight(box_height), ratio1(ratio1), ratio2(ratio2) {}
void setAll(int feature_size, int shrinkage, int box_width, int box_height, int ratio1, int ratio2)
{
this->featureSize = feature_size;
this->shrinkage = shrinkage;
this->boxWidth = box_width;
this->boxHeight = box_height;
this->ratio1 = ratio1;
this->ratio2 = ratio2;
}
void print()
{
std::cout << "fsize: " << featureSize << "\tshrinkage: " << shrinkage <<
"\t box W:" << boxWidth << "\tbox H: " << boxHeight <<
"\t x ratio:" << ratio1 << "\t y ratio:" << ratio2 << std::endl;
}
};
class MobilenetDetection : public DetectionNN
{
private:
float IoUThreshold = 0.45;
float centerVariance = 0.1;
float sizeVariance = 0.2;
int imageSize;
float *priors = nullptr;
int nPriors = 0;
float *locations_h, *confidences_h;
void generate_ssd_priors(const SSDSpec *specs, const int n_specs, bool clamp = true);
void convert_locatios_to_boxes_and_center();
float iou(const tk::dnn::box &a, const tk::dnn::box &b);
public:
MobilenetDetection() {};
~MobilenetDetection() {};
bool init(const std::string& tensor_path, const int n_classes, const int n_batches=1);
void preprocess(cv::Mat &frame, const int bi=0);
void postprocess(const int bi=0,const bool mAP=false);
};
} // namespace dnn
} // namespace tk
#endif /*MOBILENETDETECTION_H*/
+76
View File
@@ -0,0 +1,76 @@
#ifndef NETWORK_H
#define NETWORK_H
#include <string>
#include "utils.h"
namespace tk { namespace dnn {
/**
Data rapresentation beetween layers
n = batch size
c = channels
h = heigth (lines)
w = width (rows)
l = lenght (3rd dimension)
*/
struct dataDim_t {
int n, c, h, w, l;
dataDim_t() : n(1), c(1), h(1), w(1), l(1) {};
dataDim_t(int _n, int _c, int _h, int _w, int _l = 1) :
n(_n), c(_c), h(_h), w(_w), l(_l) {};
void print() {
std::cout<<"Data dim: "<<n<<" "<<c<<" "<<h<<" "<<w<<" "<<l<<"\n";
}
int tot() {
return n*c*h*w*l;
}
};
class Layer;
const int MAX_LAYERS = 512;
class Network {
public:
Network(dataDim_t input_dim);
virtual ~Network();
void releaseLayers();
/**
Do inferece for every added layer
*/
dnnType* infer(dataDim_t &dim, dnnType* data);
bool addLayer(Layer *l);
void print();
const char *getNetworkRTName(const char *network_name);
cudnnDataType_t dataType;
cudnnTensorFormat_t tensorFormat;
cudnnHandle_t cudnnHandle;
cublasHandle_t cublasHandle;
Layer* layers[MAX_LAYERS]; //contains layers of the net
int num_layers; //current number of layers
dataDim_t input_dim;
dataDim_t getOutputDim();
bool fp16, dla, int8;
int maxBatchSize;
bool dontLoadWeights;
std::string fileImgList;
std::string fileLabelList;
std::string networkName;
std::string networkNameRT;
};
}}
#endif //NETWORK_H
+120
View File
@@ -0,0 +1,120 @@
#ifndef NETWORKRT_H
#define NETWORKRT_H
#include <string.h> // memcpy
#include "utils.h"
#include "Network.h"
#include "Layer.h"
#include "NvInfer.h"
namespace tk { namespace dnn {
template<typename T> void writeBUF(char*& buffer, const T& val)
{
*reinterpret_cast<T*>(buffer) = val;
buffer += sizeof(T);
}
template<typename T> T readBUF(const char*& buffer)
{
T val = *reinterpret_cast<const T*>(buffer);
buffer += sizeof(T);
return val;
}
using namespace nvinfer1;
#include "pluginsRT/ActivationLeakyRT.h"
#include "pluginsRT/ActivationReLUCeilingRT.h"
#include "pluginsRT/ActivationMishRT.h"
#include "pluginsRT/ReorgRT.h"
#include "pluginsRT/RegionRT.h"
#include "pluginsRT/RouteRT.h"
#include "pluginsRT/ShortcutRT.h"
#include "pluginsRT/YoloRT.h"
#include "pluginsRT/UpsampleRT.h"
#include "pluginsRT/ResizeLayerRT.h"
#include "pluginsRT/DeformableConvRT.h"
#include "pluginsRT/FlattenConcatRT.h"
#include "pluginsRT/ReshapeRT.h"
#include "pluginsRT/MaxPoolingFixedSizeRT.h"
class PluginFactory : IPluginFactory
{
public:
YoloRT *yolos[16];
int n_yolos;
virtual IPlugin* createPlugin(const char* layerName, const void* serialData, size_t serialLength);
};
class NetworkRT {
public:
nvinfer1::DataType dtRT;
nvinfer1::IBuilder *builderRT;
nvinfer1::IRuntime *runtimeRT;
nvinfer1::INetworkDefinition *networkRT;
#if NV_TENSORRT_MAJOR >= 6
nvinfer1::IBuilderConfig *configRT;
#endif
nvinfer1::ICudaEngine *engineRT;
nvinfer1::IExecutionContext *contextRT;
const static int MAX_BUFFERS_RT = 10;
void* buffersRT[MAX_BUFFERS_RT];
dataDim_t buffersDIM[MAX_BUFFERS_RT];
int buf_input_idx, buf_output_idx;
dataDim_t input_dim, output_dim;
dnnType *output;
cudaStream_t stream;
PluginFactory *pluginFactory;
NetworkRT(Network *net, const char *name);
virtual ~NetworkRT();
int getMaxBatchSize() {
if(engineRT != nullptr)
return engineRT->getMaxBatchSize();
else
return 0;
}
int getBuffersN() {
if(engineRT != nullptr)
return engineRT->getNbBindings();
else
return 0;
}
/**
Do inferece
*/
dnnType* infer(dataDim_t &dim, dnnType* data);
void enqueue(int batchSize = 1);
nvinfer1::ILayer* convert_layer(nvinfer1::ITensor *input, Layer *l);
nvinfer1::ILayer* convert_layer(nvinfer1::ITensor *input, Conv2d *l);
nvinfer1::ILayer* convert_layer(nvinfer1::ITensor *input, Activation *l);
nvinfer1::ILayer* convert_layer(nvinfer1::ITensor *input, Dense *l);
nvinfer1::ILayer* convert_layer(nvinfer1::ITensor *input, Pooling *l);
nvinfer1::ILayer* convert_layer(nvinfer1::ITensor *input, Softmax *l);
nvinfer1::ILayer* convert_layer(nvinfer1::ITensor *input, Route *l);
nvinfer1::ILayer* convert_layer(nvinfer1::ITensor *input, Flatten *l);
nvinfer1::ILayer* convert_layer(nvinfer1::ITensor *input, Reshape *l);
nvinfer1::ILayer* convert_layer(nvinfer1::ITensor *input, Reorg *l);
nvinfer1::ILayer* convert_layer(nvinfer1::ITensor *input, Region *l);
nvinfer1::ILayer* convert_layer(nvinfer1::ITensor *input, Shortcut *l);
nvinfer1::ILayer* convert_layer(nvinfer1::ITensor *input, Yolo *l);
nvinfer1::ILayer* convert_layer(nvinfer1::ITensor *input, Upsample *l);
nvinfer1::ILayer* convert_layer(nvinfer1::ITensor *input, DeformConv2d *l);
bool serialize(const char *filename);
bool deserialize(const char *filename);
};
}}
#endif //NETWORKRT_H
+12
View File
@@ -0,0 +1,12 @@
#pragma once
#include <iostream>
#include <opencv2/core/types.hpp>
#include "tkdnn.h"
namespace tk { namespace dnn {
cv::Mat vizFloat2colorMap(cv::Mat map);
cv::Mat vizData2Mat(dnnType *dataInput, tk::dnn::dataDim_t dim, int imgdim);
cv::Mat vizLayer2Mat(tk::dnn::Network *net, int layer, int imgdim = 1000);
}}
+36
View File
@@ -0,0 +1,36 @@
#ifndef Yolo3Detection_H
#define Yolo3Detection_H
#include <opencv2/videoio.hpp>
#include "opencv2/opencv.hpp"
#include "DetectionNN.h"
namespace tk { namespace dnn {
class Yolo3Detection : public DetectionNN
{
private:
int num = 0;
int nMasks = 0;
int nDets = 0;
tk::dnn::Yolo::detection *dets = nullptr;
tk::dnn::Yolo* yolo[3];
tk::dnn::Yolo* getYoloLayer(int n=0);
cv::Mat bgr_h;
public:
Yolo3Detection() {};
~Yolo3Detection() {};
bool init(const std::string& tensor_path, const int n_classes=80, const int n_batches=1);
void preprocess(cv::Mat &frame, const int bi=0);
void postprocess(const int bi=0,const bool mAP=false);
};
} // namespace dnn
} // namespace tk
#endif /* Yolo3Detection_H*/
+116
View File
@@ -0,0 +1,116 @@
#ifndef EVALUATION_H
#define EVALUATION_H
#include <iostream>
#include <vector>
#include <algorithm>
#include <yaml-cpp/yaml.h>
#include "tkdnn.h"
#include "BoundingBox.h"
namespace tk { namespace dnn {
struct Frame
{
std::string lFilename;
std::string iFilename;
std::vector<BoundingBox> gt;
std::vector<BoundingBox> det;
void print() const;
};
struct PR
{
double precision = 0;
double recall = 0;
int tp = 0, fp = 0, fn = 0;
void print();
};
void readmAPParams( const char* config_filename, int& classes, int& map_points,
int& map_levels, float& map_step, float& IoU_thresh,
float& conf_thresh, bool& verbose);
/**
* This method computes the mean Average Precision for a set of detections and
* groundtruths. It returns the mAP for a given IoU threshold, and a given
* confidence threshold over all the classes.
*
* @param images collection of frames on which to compute the metrics
* @param classes number of classes of the considered dataset
* @param IoU_thresh threshold used to compute Intersection over Union
* @param conf_thresh threshold used to filter bounding boxes based on their
* confidence (or probability)
* @param map_points number of point used to compute the mAP. if 0 is given,
* all the recall levels are evaluated, otherwise only
* map_point recall levels are used. For COCO evaluation
* 101 points are used.
* @param verbose is set to true, prints on screen additional info
*
* @return mAP computed
*/
double computeMap( std::vector<Frame> &images,const int classes,
const float IoU_thresh, const float conf_thresh=0.3,
const int map_points=101, const bool verbose=false);
/**
* This method computes the mean Average Precision for a set of detections and
* groundtruths on several IoU thresholds. It is used to compute, for example,
* the most used metric in Object Detection, namely the mAP 0.5:0.95, which is
* the average among the mAP for IoU level from 0.5 to 0.95 with a step of 0.05.
*
* @param images collection of frames on which to compute the metrics
* @param classes number of classes of the considered dataset
* @param IoU_thresh starting threshold used to compute Intersection over Union
* @param conf_thresh threshold used to filter bounding boxes based on their
* confidence (or probability)
* @param map_points number of point used to compute the mAP. if 0 is given,
* all the recall levels are evaluated, otherwise only
* map_point recall levels are used. For COCO evaluation
* 101 points are used.
* @param map_step step used to increment IoU theshold
* @param map_levels number of IoU step to perform
* @param verbose is set to true, prints on screen additional info
* @param write_on_file if set to true, the results produced by this function
* are written on file
* @param net name of the considerd neural network
*
* @return mAP IoU_tresh:IoU_tresh+map_step*map_levels (e.g. mAP 0.5:0.95 when
* map_step=0.05 and map_levels=10)
*/
double computeMapNIoULevels(std::vector<Frame> &images,const int classes,
const float i_IoU_thresh=0.5, const float conf_thresh=0.3,
const int map_points=101, const float map_step=0.05,
const int map_levels=10, const bool verbose=false,
const bool write_on_file = false, std::string net = "");
/**
* This method computes the numper of True Positive (TP), False Positive (FP),
* False Negative (FN), precision, recall and f1-score.
* Those values are computer over all the detections, over all the classes.
*
* @param images collection of frames on which to compute the metrics
* @param classes number of classes of the considered dataset
* @param IoU_thresh threshold used to compute Intersection over Union
* @param conf_thresh threshold used to filter bounding boxes based on their
* confidence (or probability)
* @param verbose is set to true, prints on screen additional info
* @param write_on_file if set to true, the results produced by this function
* are written on file
* @param net name of the considerd neural network
*/
void computeTPFPFN( std::vector<Frame> &images,const int classes,
const float IoU_thresh=0.5, const float conf_thresh=0.3,
bool verbose=false, const bool write_on_file=false,
std::string net="");
void printJsonCOCOFormat(std::ofstream *out_file, const std::string image_path, std::vector<tk::dnn::box> bbox, const int classes, const int w, const int h);
}}
#endif /*EVALUATION_H*/
+51
View File
@@ -0,0 +1,51 @@
#ifndef KERNELS_H
#define KERNELS_H
#include "utils.h"
void activationELUForward(dnnType *srcData, dnnType *dstData, int size, cudaStream_t stream = cudaStream_t(0));
void activationLEAKYForward(dnnType *srcData, dnnType *dstData, int size, cudaStream_t stream = cudaStream_t(0));
void activationReLUCeilingForward(dnnType *srcData, dnnType *dstData, int size, const float ceiling, cudaStream_t stream = cudaStream_t(0));
void activationLOGISTICForward(dnnType *srcData, dnnType *dstData, int size, cudaStream_t stream = cudaStream_t(0));
void activationSIGMOIDForward(dnnType *srcData, dnnType *dstData, int size, cudaStream_t stream = cudaStream_t(0));
void activationMishForward(dnnType* srcData, dnnType* dstData, int size, cudaStream_t stream= cudaStream_t(0));
void fill(dnnType *data, int size, dnnType val, cudaStream_t stream = cudaStream_t(0));
void resizeForward(dnnType *srcData, dnnType *dstData, int n, int i_c, int i_h, int i_w,
int o_c, int o_h, int o_w, cudaStream_t stream = cudaStream_t(0));
void reorgForward(dnnType *srcData, dnnType *dstData,
int n, int c, int h, int w, int stride, cudaStream_t stream = cudaStream_t(0));
void MaxPoolingForward(dnnType *srcData, dnnType *dstData, int n, int c, int h, int w, int stride_x, int stride_y, int size, int padding, cudaStream_t stream = cudaStream_t(0));
void softmaxForward(float *input, int n, int batch, int batch_offset,
int groups, int group_offset, int stride, float temp, float *output, cudaStream_t stream = cudaStream_t(0));
void shortcutForward(dnnType *srcData, dnnType *dstData, int n1, int c1, int h1, int w1, int s1,
int n2, int c2, int h2, int w2, int s2,
cudaStream_t stream = cudaStream_t(0));
void upsampleForward(dnnType *srcData, dnnType *dstData,
int n, int c, int h, int w, int s, int forward, float scale,
cudaStream_t stream = cudaStream_t(0));
void float2half(float *srcData, __half *dstData, int size, const cudaStream_t stream = cudaStream_t(0));
void dcnV2CudaForward(cublasStatus_t stat, cublasHandle_t handle,
float *input, float *weight,
float *bias, float *ones,
float *offset, float *mask,
float *output, float *columns,
int kernel_h, int kernel_w,
const int stride_h, const int stride_w,
const int pad_h, const int pad_w,
const int dilation_h, const int dilation_w,
const int deformable_group, const int batch_id,
const int in_n, const int in_c, const int in_h, const int in_w,
const int out_n, const int out_c, const int out_h, const int out_w,
const int dst_dim, cudaStream_t stream = cudaStream_t(0));
void scalAdd(dnnType* dstData, int size, float alpha, float beta, int inc, cudaStream_t stream = cudaStream_t(0));
#endif //KERNELS_H
+39
View File
@@ -0,0 +1,39 @@
#ifndef KERNELSTHRUST_H
#define KERNELSTHRUST_H
#include <thrust/sort.h>
#include <thrust/execution_policy.h>
#include <thrust/functional.h>
#include <thrust/transform.h>
#include <thrust/iterator/constant_iterator.h>
#include <thrust/gather.h>
#include <thrust/copy.h>
#include "tkdnn.h"
struct threshold : public thrust::binary_function<float,float,float>
{
__host__ __device__
float operator()(float x, float y) {
double toll = 1e-6;
if(fabsf(x-y)>toll)
return 0.0f;
else
return x;
}
};
void sort(dnnType *src_begin, dnnType *src_end, int *idsrc);
void topk(dnnType *src_begin, int *idsrc, int K, float *topk_scores,
int *topk_inds, float *topk_ys, float *topk_xs);
// void sortAndTopKonDevice(dnnType *src_begin, int *idsrc, float *topk_scores, int *topk_inds, float *topk_ys, float *topk_xs, const int size, const int K, const int n_classes);
void normalize(float *bgr, const int ch, const int h, const int w, const float *mean, const float *stddev);
void subtractWithThreshold(dnnType *src_begin, dnnType *src_end, dnnType *src2_begin, dnnType *src_out, struct threshold op);
void topKxyclasses(int *ids_begin, int *ids_end, const int K, const int size, const int wh, int *clses, int *xs, int *ys);
void topKxyAddOffset(int * ids_begin, const int K, const int size, int *intxs_begin, int *intys_begin,
float *xs_begin, float *ys_begin, dnnType *src_begin, float *src_out, int *ids_out);
void bboxes(int * ids_begin, const int K, const int size, float *xs_begin, float *ys_begin,
dnnType *src_begin, float *bbx0, float *bbx1, float *bby0, float *bby1, float *src_out, int *ids_out);
#endif //KERNELSTHRUST_H
@@ -0,0 +1,60 @@
#include<cassert>
#include "../kernels.h"
class ActivationLeakyRT : public IPlugin {
public:
ActivationLeakyRT() {
}
~ActivationLeakyRT(){
}
int getNbOutputs() const override {
return 1;
}
Dims getOutputDimensions(int index, const Dims* inputs, int nbInputDims) override {
return inputs[0];
}
void configure(const Dims* inputDims, int nbInputs, const Dims* outputDims, int nbOutputs, int maxBatchSize) override {
size = 1;
for(int i=0; i<outputDims[0].nbDims; i++)
size *= outputDims[0].d[i];
}
int initialize() override {
return 0;
}
virtual void terminate() override {
}
virtual size_t getWorkspaceSize(int maxBatchSize) const override {
return 0;
}
virtual int enqueue(int batchSize, const void*const * inputs, void** outputs, void* workspace, cudaStream_t stream) override {
activationLEAKYForward((dnnType*)reinterpret_cast<const dnnType*>(inputs[0]),
reinterpret_cast<dnnType*>(outputs[0]), batchSize*size, stream);
return 0;
}
virtual size_t getSerializationSize() override {
return 1*sizeof(int);
}
virtual void serialize(void* buffer) override {
char *buf = reinterpret_cast<char*>(buffer);
tk::dnn::writeBUF(buf, size);
}
int size;
};
@@ -0,0 +1,60 @@
#include<cassert>
#include "../kernels.h"
class ActivationMishRT : public IPlugin {
public:
ActivationMishRT() {
}
~ActivationMishRT(){
}
int getNbOutputs() const override {
return 1;
}
Dims getOutputDimensions(int index, const Dims* inputs, int nbInputDims) override {
return inputs[0];
}
void configure(const Dims* inputDims, int nbInputs, const Dims* outputDims, int nbOutputs, int maxBatchSize) override {
size = 1;
for(int i=0; i<outputDims[0].nbDims; i++)
size *= outputDims[0].d[i];
}
int initialize() override {
return 0;
}
virtual void terminate() override {
}
virtual size_t getWorkspaceSize(int maxBatchSize) const override {
return 0;
}
virtual int enqueue(int batchSize, const void*const * inputs, void** outputs, void* workspace, cudaStream_t stream) override {
activationMishForward((dnnType*)reinterpret_cast<const dnnType*>(inputs[0]),
reinterpret_cast<dnnType*>(outputs[0]), batchSize*size, stream);
return 0;
}
virtual size_t getSerializationSize() override {
return 1*sizeof(int);
}
virtual void serialize(void* buffer) override {
char *buf = reinterpret_cast<char*>(buffer);
tk::dnn::writeBUF(buf, size);
}
int size;
};
@@ -0,0 +1,62 @@
#include<cassert>
#include "../kernels.h"
class ActivationReLUCeiling : public IPlugin {
public:
ActivationReLUCeiling(const float ceiling) {
this->ceiling = ceiling;
}
~ActivationReLUCeiling(){
}
int getNbOutputs() const override {
return 1;
}
Dims getOutputDimensions(int index, const Dims* inputs, int nbInputDims) override {
return inputs[0];
}
void configure(const Dims* inputDims, int nbInputs, const Dims* outputDims, int nbOutputs, int maxBatchSize) override {
size = 1;
for(int i=0; i<outputDims[0].nbDims; i++)
size *= outputDims[0].d[i];
}
int initialize() override {
return 0;
}
virtual void terminate() override {
}
virtual size_t getWorkspaceSize(int maxBatchSize) const override {
return 0;
}
virtual int enqueue(int batchSize, const void*const * inputs, void** outputs, void* workspace, cudaStream_t stream) override {
activationReLUCeilingForward((dnnType*)reinterpret_cast<const dnnType*>(inputs[0]),
reinterpret_cast<dnnType*>(outputs[0]), batchSize*size, ceiling, stream);
return 0;
}
virtual size_t getSerializationSize() override {
return 1*sizeof(int) + 1*sizeof(float);
}
virtual void serialize(void* buffer) override {
char *buf = reinterpret_cast<char*>(buffer);
tk::dnn::writeBUF(buf, ceiling);
tk::dnn::writeBUF(buf, size);
}
int size;
float ceiling;
};
@@ -0,0 +1,60 @@
#include<cassert>
#include "../kernels.h"
class ActivationSigmoidRT : public IPlugin {
public:
ActivationSigmoidRT() {
}
~ActivationSigmoidRT(){
}
int getNbOutputs() const override {
return 1;
}
Dims getOutputDimensions(int index, const Dims* inputs, int nbInputDims) override {
return inputs[0];
}
void configure(const Dims* inputDims, int nbInputs, const Dims* outputDims, int nbOutputs, int maxBatchSize) override {
size = 1;
for(int i=0; i<outputDims[0].nbDims; i++)
size *= outputDims[0].d[i];
}
int initialize() override {
return 0;
}
virtual void terminate() override {
}
virtual size_t getWorkspaceSize(int maxBatchSize) const override {
return 0;
}
virtual int enqueue(int batchSize, const void*const * inputs, void** outputs, void* workspace, cudaStream_t stream) override {
activationSIGMOIDForward((dnnType*)reinterpret_cast<const dnnType*>(inputs[0]),
reinterpret_cast<dnnType*>(outputs[0]), batchSize*size, stream);
return 0;
}
virtual size_t getSerializationSize() override {
return 1*sizeof(int);
}
virtual void serialize(void* buffer) override {
char *buf = reinterpret_cast<char*>(buffer);
tk::dnn::writeBUF(buf, size);
}
int size;
};
+195
View File
@@ -0,0 +1,195 @@
#include<cassert>
#include "../kernels.h"
class DeformableConvRT : public IPlugin {
public:
DeformableConvRT(int chunk_dim, int kh, int kw, int sh, int sw, int ph, int pw,
int deformableGroup, int i_n, int i_c, int i_h, int i_w,
int o_n, int o_c, int o_h, int o_w,
tk::dnn::DeformConv2d *deformable = nullptr) {
this->chunk_dim = chunk_dim;
this->kh = kh;
this->kw = kw;
this->sh = sh;
this->sw = sw;
this->ph = ph;
this->pw = pw;
this->deformableGroup = deformableGroup;
this->i_n = i_n;
this->i_c = i_c;
this->i_h = i_h;
this->i_w = i_w;
this->o_n = o_n;
this->o_c = o_c;
this->o_h = o_h;
this->o_w = o_w;
height_ones = (i_h + 2 * ph - (1 * (kh - 1) + 1)) / sh + 1;
width_ones = (i_w + 2 * pw - (1 * (kw - 1) + 1)) / sw + 1;
dim_ones = i_c * kh * kw * 1 * height_ones * width_ones;
std::cout<<i_c * o_c * kh * kw * 1<<"\n";
checkCuda( cudaMalloc(&data_d, i_c * o_c * kh * kw * 1 * sizeof(dnnType)));
checkCuda( cudaMalloc(&bias2_d, o_c*sizeof(dnnType)));
checkCuda( cudaMalloc(&ones_d1, height_ones * width_ones * sizeof(dnnType)));
checkCuda( cudaMalloc(&offset, 2*chunk_dim*sizeof(dnnType)));
checkCuda( cudaMalloc(&mask, chunk_dim*sizeof(dnnType)));
checkCuda( cudaMalloc(&ones_d2, dim_ones*sizeof(dnnType)));
if(deformable != nullptr) {
this->defRT = deformable;
checkCuda( cudaMemcpy(data_d, deformable->data_d, sizeof(dnnType)*i_c * o_c * kh * kw * 1, cudaMemcpyDeviceToDevice) );
checkCuda( cudaMemcpy(bias2_d, deformable->bias2_d, sizeof(dnnType)*o_c, cudaMemcpyDeviceToDevice) );
checkCuda( cudaMemcpy(ones_d1, deformable->ones_d1, sizeof(dnnType)*height_ones*width_ones, cudaMemcpyDeviceToDevice) );
checkCuda( cudaMemcpy(offset, deformable->offset, sizeof(dnnType)*2*chunk_dim, cudaMemcpyDeviceToDevice) );
checkCuda( cudaMemcpy(mask, deformable->mask, sizeof(dnnType)*chunk_dim, cudaMemcpyDeviceToDevice) );
checkCuda( cudaMemcpy(ones_d2, deformable->ones_d2, sizeof(dnnType)*dim_ones, cudaMemcpyDeviceToDevice) );
}
stat = cublasCreate(&handle);
if (stat != CUBLAS_STATUS_SUCCESS)
FatalError("CUBLAS initialization failed\n");
}
~DeformableConvRT() {
checkCuda( cudaFree(data_d) );
checkCuda( cudaFree(bias2_d) );
checkCuda( cudaFree(ones_d1) );
checkCuda( cudaFree(offset) );
checkCuda( cudaFree(mask) );
checkCuda( cudaFree(ones_d2) );
cublasDestroy(handle);
}
int getNbOutputs() const override {
return 1;
}
Dims getOutputDimensions(int index, const Dims* inputs, int nbInputDims) override {
return DimsCHW{defRT->output_dim.c, defRT->output_dim.h, defRT->output_dim.w};
}
void configure(const Dims* inputDims, int nbInputs, const Dims* outputDims, int nbOutputs, int maxBatchSize) override { }
int initialize() override {
return 0;
}
virtual void terminate() override { }
virtual size_t getWorkspaceSize(int maxBatchSize) const override {
return 0;
}
virtual int enqueue(int batchSize, const void*const * inputs, void** outputs, void* workspace, cudaStream_t stream) override {
dnnType *srcData = (dnnType*)reinterpret_cast<const dnnType*>(inputs[0]);
dnnType *output_conv = (dnnType*)reinterpret_cast<const dnnType*>(inputs[1]);
// split conv2d outputs into offset to mask
for(int b=0; b<batchSize; b++) {
checkCuda(cudaMemcpy(offset, output_conv + b * 3 * chunk_dim, 2*chunk_dim*sizeof(dnnType), cudaMemcpyDeviceToDevice));
checkCuda(cudaMemcpy(mask, output_conv + b * 3 * chunk_dim + 2*chunk_dim, chunk_dim*sizeof(dnnType), cudaMemcpyDeviceToDevice));
// kernel sigmoide
activationSIGMOIDForward(mask, mask, chunk_dim);
// deformable convolution
dcnV2CudaForward(stat, handle,
srcData, data_d,
bias2_d, ones_d1,
offset, mask,
reinterpret_cast<dnnType*>(outputs[0]), ones_d2,
kh, kw,
sh, sw,
ph, pw,
1, 1,
deformableGroup, b,
i_n, i_c, i_h, i_w,
o_n, o_c, o_h, o_w,
chunk_dim);
}
return 0;
}
virtual size_t getSerializationSize() override {
return 16 * sizeof(int) + chunk_dim * 3 * sizeof(dnnType) + (i_c * o_c * kh * kw * 1 ) * sizeof(dnnType) +
o_c * sizeof(dnnType) + height_ones * width_ones * sizeof(dnnType) + dim_ones * sizeof(dnnType);
}
virtual void serialize(void* buffer) override {
char *buf = reinterpret_cast<char*>(buffer);
tk::dnn::writeBUF(buf, chunk_dim);
tk::dnn::writeBUF(buf, kh);
tk::dnn::writeBUF(buf, kw);
tk::dnn::writeBUF(buf, sh);
tk::dnn::writeBUF(buf, sw);
tk::dnn::writeBUF(buf, ph);
tk::dnn::writeBUF(buf, pw);
tk::dnn::writeBUF(buf, deformableGroup);
tk::dnn::writeBUF(buf, i_n);
tk::dnn::writeBUF(buf, i_c);
tk::dnn::writeBUF(buf, i_h);
tk::dnn::writeBUF(buf, i_w);
tk::dnn::writeBUF(buf, o_n);
tk::dnn::writeBUF(buf, o_c);
tk::dnn::writeBUF(buf, o_h);
tk::dnn::writeBUF(buf, o_w);
dnnType *aus = new dnnType[chunk_dim*2];
checkCuda( cudaMemcpy(aus, offset, sizeof(dnnType)*2*chunk_dim, cudaMemcpyDeviceToHost) );
for(int i=0; i<chunk_dim*2; i++)
tk::dnn::writeBUF(buf, aus[i]);
free(aus);
aus = new dnnType[chunk_dim];
checkCuda( cudaMemcpy(aus, mask, sizeof(dnnType)*chunk_dim, cudaMemcpyDeviceToHost) );
for(int i=0; i<chunk_dim; i++)
tk::dnn::writeBUF(buf, aus[i]);
free(aus);
aus = new dnnType[(i_c * o_c * kh * kw * 1 )];
checkCuda( cudaMemcpy(aus, data_d, sizeof(dnnType)*(i_c * o_c * kh * kw * 1 ), cudaMemcpyDeviceToHost) );
for(int i=0; i<(i_c * o_c * kh * kw * 1 ); i++)
tk::dnn::writeBUF(buf, aus[i]);
free(aus);
aus = new dnnType[o_c];
checkCuda( cudaMemcpy(aus, bias2_d, sizeof(dnnType)*o_c, cudaMemcpyDeviceToHost) );
for(int i=0; i < o_c; i++)
tk::dnn::writeBUF(buf, aus[i]);
free(aus);
aus = new dnnType[height_ones * width_ones];
checkCuda( cudaMemcpy(aus, ones_d1, sizeof(dnnType)*height_ones * width_ones, cudaMemcpyDeviceToHost) );
for(int i=0; i<height_ones * width_ones; i++)
tk::dnn::writeBUF(buf, aus[i]);
free(aus);
aus = new dnnType[dim_ones];
checkCuda( cudaMemcpy(aus, ones_d2, sizeof(dnnType)*dim_ones, cudaMemcpyDeviceToHost) );
for(int i=0; i<dim_ones; i++)
tk::dnn::writeBUF(buf, aus[i]);
free(aus);
}
cublasStatus_t stat;
cublasHandle_t handle;
int i_n, i_c, i_h, i_w;
int o_n, o_c, o_h, o_w;
int size;
int chunk_dim;
int kh, kw;
int sh, sw;
int ph, pw;
int deformableGroup;
int height_ones;
int width_ones;
int dim_ones;
dnnType *data_d;
dnnType *bias2_d;
dnnType *ones_d1;
dnnType * offset;
dnnType * mask;
dnnType *ones_d2;
// dnnType *input_n;
// dnnType *offset_n;
// dnnType *mask_n;
// dnnType *output_n;
tk::dnn::DeformConv2d *defRT;
};
+80
View File
@@ -0,0 +1,80 @@
#include<cassert>
class FlattenConcatRT : public IPlugin {
public:
FlattenConcatRT() {
stat = cublasCreate(&handle);
if (stat != CUBLAS_STATUS_SUCCESS) {
printf ("CUBLAS initialization failed\n");
return;
}
}
~FlattenConcatRT(){
}
int getNbOutputs() const override {
return 1;
}
Dims getOutputDimensions(int index, const Dims* inputs, int nbInputDims) override {
return DimsCHW{ inputs[0].d[0] * inputs[0].d[1] * inputs[0].d[2], 1, 1};
}
void configure(const Dims* inputDims, int nbInputs, const Dims* outputDims, int nbOutputs, int maxBatchSize) override {
assert(nbOutputs == 1 && nbInputs ==1);
rows = inputDims[0].d[0];
cols = inputDims[0].d[1] * inputDims[0].d[2];
c = inputDims[0].d[0] * inputDims[0].d[1] * inputDims[0].d[2];
h = 1;
w = 1;
}
int initialize() override {
return 0;
}
virtual void terminate() override {
checkERROR(cublasDestroy(handle));
}
virtual size_t getWorkspaceSize(int maxBatchSize) const override {
return 0;
}
virtual int enqueue(int batchSize, const void*const * inputs, void** outputs, void* workspace, cudaStream_t stream) override {
dnnType *srcData = (dnnType*)reinterpret_cast<const dnnType*>(inputs[0]);
dnnType *dstData = reinterpret_cast<dnnType*>(outputs[0]);
checkCuda( cudaMemcpyAsync(dstData, srcData, batchSize*rows*cols*sizeof(dnnType), cudaMemcpyDeviceToDevice, stream));
checkERROR( cublasSetStream(handle, stream) );
for(int i=0; i<batchSize; i++) {
float const alpha(1.0);
float const beta(0.0);
int offset = i*rows*cols;
checkERROR( cublasSgeam( handle, CUBLAS_OP_T, CUBLAS_OP_N, rows, cols, &alpha, srcData + offset, cols, &beta, srcData + offset, rows, dstData + offset, rows ));
}
return 0;
}
virtual size_t getSerializationSize() override {
return 5*sizeof(int);
}
virtual void serialize(void* buffer) override {
char *buf = reinterpret_cast<char*>(buffer);
tk::dnn::writeBUF(buf, c);
tk::dnn::writeBUF(buf, h);
tk::dnn::writeBUF(buf, w);
tk::dnn::writeBUF(buf, rows);
tk::dnn::writeBUF(buf, cols);
}
int c, h, w;
int rows, cols;
cublasStatus_t stat;
cublasHandle_t handle;
};
+168
View File
@@ -0,0 +1,168 @@
#include <vector>
#include <assert.h>
#include <algorithm>
#include <iterator>
#include "NvInfer.h"
class BatchStream
{
public:
BatchStream(tk::dnn::dataDim_t dim, int batchSize, int maxBatches)
{
mBatchSize = batchSize;
mMaxBatches = maxBatches;
mDims = nvinfer1::DimsNCHW{ dim.n, dim.c, dim.h, dim.w };
mImageSize = mDims.c()*mDims.h()*mDims.w();
mBatch.resize(mBatchSize*mImageSize, 0);
mLabels.resize(mBatchSize, 0);
mFileBatch.resize(mDims.n()*mImageSize, 0);
mFileLabels.resize(mDims.n(), 0);
reset(0);
}
void reset(int firstBatch)
{
mBatchCount = 0;
mFileCount = 0;
mFileBatchPos = mDims.n();
skip(firstBatch);
}
bool next()
{
std::cout<<"Next batch: "<<mBatchCount<<" of "<<mMaxBatches<<"\n";
if (mBatchCount == mMaxBatches)
return false;
for (int csize = 1, batchPos = 0; batchPos < mBatchSize; batchPos += csize, mFileBatchPos += csize)
{
assert(mFileBatchPos > 0 && mFileBatchPos <= mDims.n());
if (mFileBatchPos == mDims.n() && !update())
return false;
// copy the smaller of: elements left to fulfill the request, or elements left in the file buffer.
csize = std::min(mBatchSize - batchPos, mDims.n() - mFileBatchPos);
std::copy_n(getFileBatch() + mFileBatchPos * mImageSize, csize * mImageSize, getBatch() + batchPos * mImageSize);
std::copy_n(getFileLabels() + mFileBatchPos, csize, getLabels() + batchPos);
}
mBatchCount++;
return true;
}
void skip(int skipCount)
{
if (mBatchSize >= mDims.n() && mBatchSize%mDims.n() == 0 && mFileBatchPos == mDims.n())
{
mFileCount += skipCount * mBatchSize / mDims.n();
std::cout<<mFileCount<<"\n";
return;
}
int x = mBatchCount;
for (int i = 0; i < skipCount; i++)
next();
mBatchCount = x;
}
float *getBatch() { return &mBatch[0]; }
float *getLabels() { return &mLabels[0]; }
int getBatchesRead() const { return mBatchCount; }
int getBatchSize() const { return mBatchSize; }
nvinfer1::DimsNCHW getDims() const { return mDims; }
private:
float* getFileBatch() { return &mFileBatch[0]; }
float* getFileLabels() { return &mFileLabels[0]; }
bool update()
{
std::string inputFileName = std::string("calibBatches/batch") + std::to_string(mFileCount++);
FILE * file = fopen(inputFileName.c_str(), "rb");
if (!file) {
FatalError("cant open batch calib file: " + inputFileName);
return false;
}
size_t readInputCount = fread(getFileBatch(), sizeof(float), mDims.n()*mImageSize, file);
size_t readLabelCount = fread(getFileLabels(), sizeof(float), mDims.n(), file);;
assert(readInputCount == size_t(mDims.n()*mImageSize) && readLabelCount == size_t(mDims.n()));
fclose(file);
mFileBatchPos = 0;
return true;
}
int mBatchSize{ 0 };
int mMaxBatches{ 0 };
int mBatchCount{ 0 };
int mFileCount{ 0 }, mFileBatchPos{ 0 };
int mImageSize{ 0 };
nvinfer1::DimsNCHW mDims;
std::vector<float> mBatch;
std::vector<float> mLabels;
std::vector<float> mFileBatch;
std::vector<float> mFileLabels;
};
class Int8EntropyCalibrator : public IInt8EntropyCalibrator
{
public:
Int8EntropyCalibrator(BatchStream& stream, int firstBatch, bool readCache = true)
: mStream(stream), mReadCache(readCache)
{
DimsNCHW dims = mStream.getDims();
mInputCount = mStream.getBatchSize() * dims.c() * dims.h() * dims.w();
checkCuda(cudaMalloc(&mDeviceInput, mInputCount * sizeof(float)));
mStream.reset(firstBatch);
}
virtual ~Int8EntropyCalibrator()
{
checkCuda(cudaFree(mDeviceInput));
}
int getBatchSize() const override { return mStream.getBatchSize(); }
bool getBatch(void* bindings[], const char* names[], int nbBindings) override
{
std::cout<<"CALIB request batch\n";
if (!mStream.next())
return false;
checkCuda(cudaMemcpy(mDeviceInput, mStream.getBatch(), mInputCount * sizeof(float), cudaMemcpyHostToDevice));
bindings[0] = mDeviceInput;
return true;
}
const void* readCalibrationCache(size_t& length) override
{
mCalibrationCache.clear();
std::ifstream input("table.calib", std::ios::binary);
input >> std::noskipws;
FatalError("rewrite different");
//if (mReadCache && input.good())
// std::copy(std::istream_iterator<char>(input), std::istream_iterator<char>(), std::back_inserter(mCalibrationCache));
length = mCalibrationCache.size();
return length ? &mCalibrationCache[0] : nullptr;
}
void writeCalibrationCache(const void* cache, size_t length) override
{
std::ofstream output("table.calib", std::ios::binary);
output.write(reinterpret_cast<const char*>(cache), length);
}
private:
BatchStream mStream;
bool mReadCache{ true };
size_t mInputCount;
void* mDeviceInput{ nullptr };
std::vector<char> mCalibrationCache;
};
@@ -0,0 +1,74 @@
#include<cassert>
#include "../kernels.h"
class MaxPoolFixedSizeRT : public IPlugin {
public:
MaxPoolFixedSizeRT(int c, int h, int w, int n, int strideH, int strideW, int winSize, int padding) {
this->c = c;
this->h = h;
this->w = w;
this->n = n;
this->stride_H = strideH;
this->stride_W = strideW;
this->winSize = winSize;
this->padding = padding;
}
~MaxPoolFixedSizeRT(){
}
int getNbOutputs() const override {
return 1;
}
Dims getOutputDimensions(int index, const Dims* inputs, int nbInputDims) override {
return DimsCHW{this->c, this->h, this->w};
}
void configure(const Dims* inputDims, int nbInputs, const Dims* outputDims, int nbOutputs, int maxBatchSize) override {
}
int initialize() override {
return 0;
}
virtual void terminate() override {
}
virtual size_t getWorkspaceSize(int maxBatchSize) const override {
return 0;
}
virtual int enqueue(int batchSize, const void*const * inputs, void** outputs, void* workspace, cudaStream_t stream) override {
//std::cout<<this->n<<" "<<this->c<<" "<<this->h<<" "<<this->w<<" "<<this->stride_H<<" "<<this->stride_W<<" "<<this->winSize<<" "<<this->padding<<std::endl;
dnnType *srcData = (dnnType*)reinterpret_cast<const dnnType*>(inputs[0]);
dnnType *dstData = reinterpret_cast<dnnType*>(outputs[0]);
MaxPoolingForward(srcData, dstData, batchSize, this->c, this->h, this->w, this->stride_H, this->stride_W, this->winSize, this->padding, stream);
return 0;
}
virtual size_t getSerializationSize() override {
return 8*sizeof(int);
}
virtual void serialize(void* buffer) override {
char *buf = reinterpret_cast<char*>(buffer);
tk::dnn::writeBUF(buf, this->c);
tk::dnn::writeBUF(buf, this->h);
tk::dnn::writeBUF(buf, this->w);
tk::dnn::writeBUF(buf, this->n);
tk::dnn::writeBUF(buf, this->stride_H);
tk::dnn::writeBUF(buf, this->stride_W);
tk::dnn::writeBUF(buf, this->winSize);
tk::dnn::writeBUF(buf, this->padding);
}
int n, c, h, w;
int stride_H, stride_W;
int winSize;
int padding;
};
+94
View File
@@ -0,0 +1,94 @@
#include<cassert>
#include "../kernels.h"
class RegionRT : public IPlugin {
public:
RegionRT(int classes, int coords, int num) {
this->classes = classes;
this->coords = coords;
this->num = num;
}
~RegionRT(){
}
int getNbOutputs() const override {
return 1;
}
Dims getOutputDimensions(int index, const Dims* inputs, int nbInputDims) override {
return inputs[0];
}
void configure(const Dims* inputDims, int nbInputs, const Dims* outputDims, int nbOutputs, int maxBatchSize) override {
c = inputDims[0].d[0];
h = inputDims[0].d[1];
w = inputDims[0].d[2];
}
int initialize() override {
return 0;
}
virtual void terminate() override {
}
virtual size_t getWorkspaceSize(int maxBatchSize) const override {
return 0;
}
virtual int enqueue(int batchSize, const void*const * inputs, void** outputs, void* workspace, cudaStream_t stream) override {
dnnType *srcData = (dnnType*)reinterpret_cast<const dnnType*>(inputs[0]);
dnnType *dstData = reinterpret_cast<dnnType*>(outputs[0]);
checkCuda( cudaMemcpyAsync(dstData, srcData, batchSize*c*h*w*sizeof(dnnType), cudaMemcpyDeviceToDevice, stream));
for (int b = 0; b < batchSize; ++b){
for(int n = 0; n < num; ++n){
int index = entry_index(b, n*w*h, 0);
activationLOGISTICForward(srcData + index, dstData + index, 2*w*h, stream);
index = entry_index(b, n*w*h, coords);
activationLOGISTICForward(srcData + index, dstData + index, w*h, stream);
}
}
//softmax start
int index = entry_index(0, 0, coords + 1);
softmaxForward( srcData + index, classes, batchSize*num,
(c*h*w)/num,
w*h, 1, w*h, 1, dstData + index, stream);
return 0;
}
virtual size_t getSerializationSize() override {
return 6*sizeof(int);
}
virtual void serialize(void* buffer) override {
char *buf = reinterpret_cast<char*>(buffer);
tk::dnn::writeBUF(buf, classes);
tk::dnn::writeBUF(buf, coords);
tk::dnn::writeBUF(buf, num);
tk::dnn::writeBUF(buf, c);
tk::dnn::writeBUF(buf, h);
tk::dnn::writeBUF(buf, w);
}
int c, h, w;
int classes, coords, num;
int entry_index(int batch, int location, int entry) {
int n = location / (w*h);
int loc = location % (w*h);
return batch*c*h*w + n*w*h*(coords+classes+1) + entry*w*h + loc;
}
};
+63
View File
@@ -0,0 +1,63 @@
#include<cassert>
#include "../kernels.h"
class ReorgRT : public IPlugin {
public:
ReorgRT(int stride) {
this->stride = stride;
}
~ReorgRT(){
}
int getNbOutputs() const override {
return 1;
}
Dims getOutputDimensions(int index, const Dims* inputs, int nbInputDims) override {
return DimsCHW{inputs[0].d[0]*stride*stride, inputs[0].d[1]/stride, inputs[0].d[2]/stride};
}
void configure(const Dims* inputDims, int nbInputs, const Dims* outputDims, int nbOutputs, int maxBatchSize) override {
c = inputDims[0].d[0];
h = inputDims[0].d[1];
w = inputDims[0].d[2];
}
int initialize() override {
return 0;
}
virtual void terminate() override {
}
virtual size_t getWorkspaceSize(int maxBatchSize) const override {
return 0;
}
virtual int enqueue(int batchSize, const void*const * inputs, void** outputs, void* workspace, cudaStream_t stream) override {
reorgForward((dnnType*)reinterpret_cast<const dnnType*>(inputs[0]),
reinterpret_cast<dnnType*>(outputs[0]),
batchSize, c, h, w, stride, stream);
return 0;
}
virtual size_t getSerializationSize() override {
return 4*sizeof(int);
}
virtual void serialize(void* buffer) override {
char *buf = reinterpret_cast<char*>(buffer);
tk::dnn::writeBUF(buf, stride);
tk::dnn::writeBUF(buf, c);
tk::dnn::writeBUF(buf, h);
tk::dnn::writeBUF(buf, w);
}
int c, h, w, stride;
};
+61
View File
@@ -0,0 +1,61 @@
#include<cassert>
class ReshapeRT : public IPlugin {
public:
ReshapeRT(dataDim_t new_dim) {
n = new_dim.n;
c = new_dim.c;
h = new_dim.h;
w = new_dim.w;
}
~ReshapeRT(){
}
int getNbOutputs() const override {
return 1;
}
Dims getOutputDimensions(int index, const Dims* inputs, int nbInputDims) override {
return DimsCHW{ c,h,w};
}
void configure(const Dims* inputDims, int nbInputs, const Dims* outputDims, int nbOutputs, int maxBatchSize) override {
}
int initialize() override {
return 0;
}
virtual void terminate() override {
}
virtual size_t getWorkspaceSize(int maxBatchSize) const override {
return 0;
}
virtual int enqueue(int batchSize, const void*const * inputs, void** outputs, void* workspace, cudaStream_t stream) override {
dnnType *srcData = (dnnType*)reinterpret_cast<const dnnType*>(inputs[0]);
dnnType *dstData = reinterpret_cast<dnnType*>(outputs[0]);
checkCuda( cudaMemcpyAsync(dstData, srcData, batchSize*c*h*w*sizeof(dnnType), cudaMemcpyDeviceToDevice, stream));
return 0;
}
virtual size_t getSerializationSize() override {
return 4*sizeof(int);
}
virtual void serialize(void* buffer) override {
char *buf = reinterpret_cast<char*>(buffer);
tk::dnn::writeBUF(buf, n);
tk::dnn::writeBUF(buf, c);
tk::dnn::writeBUF(buf, h);
tk::dnn::writeBUF(buf, w);
}
int n, c, h, w;
};
+67
View File
@@ -0,0 +1,67 @@
#include<cassert>
#include "../kernels.h"
class ResizeLayerRT : public IPlugin {
public:
ResizeLayerRT(int c, int h, int w) {
o_c = c;
o_h = h;
o_w = w;
}
~ResizeLayerRT(){
}
int getNbOutputs() const override {
return 1;
}
Dims getOutputDimensions(int index, const Dims* inputs, int nbInputDims) override {
return DimsCHW{o_c, o_h, o_w};
}
void configure(const Dims* inputDims, int nbInputs, const Dims* outputDims, int nbOutputs, int maxBatchSize) override {
i_c = inputDims[0].d[0];
i_h = inputDims[0].d[1];
i_w = inputDims[0].d[2];
}
int initialize() override {
return 0;
}
virtual void terminate() override {
}
virtual size_t getWorkspaceSize(int maxBatchSize) const override {
return 0;
}
virtual int enqueue(int batchSize, const void*const * inputs, void** outputs, void* workspace, cudaStream_t stream) override {
// printf("%d %d %d %d %d %d\n", i_c, i_w, i_h, o_c, o_w, o_h);
resizeForward((dnnType*)reinterpret_cast<const dnnType*>(inputs[0]),
reinterpret_cast<dnnType*>(outputs[0]),
batchSize, i_c, i_h, i_w, o_c, o_h, o_w, stream);
return 0;
}
virtual size_t getSerializationSize() override {
return 6*sizeof(int);
}
virtual void serialize(void* buffer) override {
char *buf = reinterpret_cast<char*>(buffer);
tk::dnn::writeBUF(buf, o_c);
tk::dnn::writeBUF(buf, o_h);
tk::dnn::writeBUF(buf, o_w);
tk::dnn::writeBUF(buf, i_c);
tk::dnn::writeBUF(buf, i_h);
tk::dnn::writeBUF(buf, i_w);
}
int i_c, i_h, i_w, o_c, o_h, o_w;
};
+95
View File
@@ -0,0 +1,95 @@
#include<cassert>
#include "../kernels.h"
class RouteRT : public IPlugin {
/**
THIS IS NOT USED ANYMORE
*/
public:
RouteRT(int groups, int group_id) {
this->groups = groups;
this->group_id = group_id;
}
~RouteRT(){
}
int getNbOutputs() const override {
return 1;
}
Dims getOutputDimensions(int index, const Dims* inputs, int nbInputDims) override {
int out_c = 0;
for(int i=0; i<nbInputDims; i++) out_c += inputs[i].d[0];
return DimsCHW{out_c/groups, inputs[0].d[1], inputs[0].d[2]};
}
void configure(const Dims* inputDims, int nbInputs, const Dims* outputDims, int nbOutputs, int maxBatchSize) override {
in = nbInputs;
c = 0;
for(int i=0; i<nbInputs; i++) {
c_in[i] = inputDims[i].d[0];
c += inputDims[i].d[0];
}
h = inputDims[0].d[1];
w = inputDims[0].d[2];
c /= groups;
}
int initialize() override {
return 0;
}
virtual void terminate() override {
}
virtual size_t getWorkspaceSize(int maxBatchSize) const override {
return 0;
}
virtual int enqueue(int batchSize, const void*const * inputs, void** outputs, void* workspace, cudaStream_t stream) override {
dnnType *dstData = reinterpret_cast<dnnType*>(outputs[0]);
for(int b=0; b<batchSize; b++) {
int offset = 0;
for(int i=0; i<in; i++) {
dnnType *input = (dnnType*)reinterpret_cast<const dnnType*>(inputs[i]);
int in_dim = c_in[i]*h*w;
int part_in_dim = in_dim / this->groups;
checkCuda( cudaMemcpyAsync(dstData + b*c*w*h + offset, input + b*c*w*h*groups + this->group_id*part_in_dim, part_in_dim*sizeof(dnnType), cudaMemcpyDeviceToDevice, stream) );
offset += part_in_dim;
}
}
return 0;
}
virtual size_t getSerializationSize() override {
return (6+MAX_INPUTS)*sizeof(int);
}
virtual void serialize(void* buffer) override {
char *buf = reinterpret_cast<char*>(buffer);
tk::dnn::writeBUF(buf, groups);
tk::dnn::writeBUF(buf, group_id);
tk::dnn::writeBUF(buf, in);
for(int i=0; i<MAX_INPUTS; i++)
tk::dnn::writeBUF(buf, c_in[i]);
tk::dnn::writeBUF(buf, c);
tk::dnn::writeBUF(buf, h);
tk::dnn::writeBUF(buf, w);
}
static const int MAX_INPUTS = 4;
int in;
int c_in[MAX_INPUTS];
int c, h, w;
int groups, group_id;
};
+74
View File
@@ -0,0 +1,74 @@
#include<cassert>
#include "../kernels.h"
class ShortcutRT : public IPlugin {
public:
ShortcutRT(tk::dnn::dataDim_t bdim) {
this->bc = bdim.c;
this->bh = bdim.h;
this->bw = bdim.w;
}
~ShortcutRT(){
}
int getNbOutputs() const override {
return 1;
}
Dims getOutputDimensions(int index, const Dims* inputs, int nbInputDims) override {
return DimsCHW{inputs[0].d[0], inputs[0].d[1], inputs[0].d[2]};
}
void configure(const Dims* inputDims, int nbInputs, const Dims* outputDims, int nbOutputs, int maxBatchSize) override {
c = inputDims[0].d[0];
h = inputDims[0].d[1];
w = inputDims[0].d[2];
}
int initialize() override {
return 0;
}
virtual void terminate() override {
}
virtual size_t getWorkspaceSize(int maxBatchSize) const override {
return 0;
}
virtual int enqueue(int batchSize, const void*const * inputs, void** outputs, void* workspace, cudaStream_t stream) override {
dnnType *srcData = (dnnType*)reinterpret_cast<const dnnType*>(inputs[0]);
dnnType *srcDataBack = (dnnType*)reinterpret_cast<const dnnType*>(inputs[1]);
dnnType *dstData = reinterpret_cast<dnnType*>(outputs[0]);
checkCuda( cudaMemcpyAsync(dstData, srcData, batchSize*c*h*w*sizeof(dnnType), cudaMemcpyDeviceToDevice, stream));
for(int b=0; b < batchSize; ++b)
shortcutForward(srcDataBack + b*bc*bh*bw, dstData + b*c*h*w, 1, c, h, w, 1, 1, bc, bh, bw, 1, stream);
return 0;
}
virtual size_t getSerializationSize() override {
return 6*sizeof(int);
}
virtual void serialize(void* buffer) override {
char *buf = reinterpret_cast<char*>(buffer);
tk::dnn::writeBUF(buf, bc);
tk::dnn::writeBUF(buf, bh);
tk::dnn::writeBUF(buf, bw);
tk::dnn::writeBUF(buf, c);
tk::dnn::writeBUF(buf, h);
tk::dnn::writeBUF(buf, w);
}
int c, h, w;
int bc, bh, bw;
};
+65
View File
@@ -0,0 +1,65 @@
#include<cassert>
#include "../kernels.h"
class UpsampleRT : public IPlugin {
public:
UpsampleRT(int stride) {
this->stride = stride;
}
~UpsampleRT(){
}
int getNbOutputs() const override {
return 1;
}
Dims getOutputDimensions(int index, const Dims* inputs, int nbInputDims) override {
return DimsCHW(inputs[0].d[0], inputs[0].d[1]*stride, inputs[0].d[2]*stride);
}
void configure(const Dims* inputDims, int nbInputs, const Dims* outputDims, int nbOutputs, int maxBatchSize) override {
c = inputDims[0].d[0];
h = inputDims[0].d[1];
w = inputDims[0].d[2];
}
int initialize() override {
return 0;
}
virtual void terminate() override {
}
virtual size_t getWorkspaceSize(int maxBatchSize) const override {
return 0;
}
virtual int enqueue(int batchSize, const void*const * inputs, void** outputs, void* workspace, cudaStream_t stream) override {
dnnType *srcData = (dnnType*)reinterpret_cast<const dnnType*>(inputs[0]);
dnnType *dstData = reinterpret_cast<dnnType*>(outputs[0]);
fill(dstData, batchSize*c*h*w*stride*stride, 0.0, stream);
upsampleForward(srcData, dstData, batchSize, c, h, w, stride, 1, 1, stream);
return 0;
}
virtual size_t getSerializationSize() override {
return 4*sizeof(int);
}
virtual void serialize(void* buffer) override {
char *buf = reinterpret_cast<char*>(buffer);
tk::dnn::writeBUF(buf, stride);
tk::dnn::writeBUF(buf, c);
tk::dnn::writeBUF(buf, h);
tk::dnn::writeBUF(buf, w);
}
int c, h, w, stride;
};
+123
View File
@@ -0,0 +1,123 @@
#include<cassert>
#include "../kernels.h"
#define YOLORT_CLASSNAME_W 256
class YoloRT : public IPlugin {
public:
YoloRT(int classes, int num, tk::dnn::Yolo *yolo = nullptr, int n_masks=3, float scale_xy=1) {
this->classes = classes;
this->num = num;
this->n_masks = n_masks;
this->scaleXY = scale_xy;
mask = new dnnType[n_masks];
bias = new dnnType[num*n_masks*2];
if(yolo != nullptr) {
memcpy(mask, yolo->mask_h, sizeof(dnnType)*n_masks);
memcpy(bias, yolo->bias_h, sizeof(dnnType)*num*n_masks*2);
classesNames = yolo->classesNames;
}
}
~YoloRT(){
}
int getNbOutputs() const override {
return 1;
}
Dims getOutputDimensions(int index, const Dims* inputs, int nbInputDims) override {
return inputs[0];
}
void configure(const Dims* inputDims, int nbInputs, const Dims* outputDims, int nbOutputs, int maxBatchSize) override {
c = inputDims[0].d[0];
h = inputDims[0].d[1];
w = inputDims[0].d[2];
}
int initialize() override {
return 0;
}
virtual void terminate() override {
}
virtual size_t getWorkspaceSize(int maxBatchSize) const override {
return 0;
}
virtual int enqueue(int batchSize, const void*const * inputs, void** outputs, void* workspace, cudaStream_t stream) override {
dnnType *srcData = (dnnType*)reinterpret_cast<const dnnType*>(inputs[0]);
dnnType *dstData = reinterpret_cast<dnnType*>(outputs[0]);
checkCuda( cudaMemcpyAsync(dstData, srcData, batchSize*c*h*w*sizeof(dnnType), cudaMemcpyDeviceToDevice, stream));
for (int b = 0; b < batchSize; ++b){
for(int n = 0; n < n_masks; ++n){
int index = entry_index(b, n*w*h, 0);
activationLOGISTICForward(srcData + index, dstData + index, 2*w*h, stream);
if (this->scaleXY != 1) scalAdd(dstData + index, 2 * w*h, this->scaleXY, -0.5*(this->scaleXY - 1), 1);
index = entry_index(b, n*w*h, 4);
activationLOGISTICForward(srcData + index, dstData + index, (1+classes)*w*h, stream);
}
}
//std::cout<<"YOLO END\n";
return 0;
}
virtual size_t getSerializationSize() override {
return 6*sizeof(int) + sizeof(float)+ n_masks*sizeof(dnnType) + num*n_masks*2*sizeof(dnnType) + YOLORT_CLASSNAME_W*classes*sizeof(char);
}
virtual void serialize(void* buffer) override {
char *buf = reinterpret_cast<char*>(buffer);
tk::dnn::writeBUF(buf, classes);
tk::dnn::writeBUF(buf, num);
tk::dnn::writeBUF(buf, n_masks);
tk::dnn::writeBUF(buf, c);
tk::dnn::writeBUF(buf, h);
tk::dnn::writeBUF(buf, w);
tk::dnn::writeBUF(buf, scaleXY);
for(int i=0; i<n_masks; i++)
tk::dnn::writeBUF(buf, mask[i]);
for(int i=0; i<n_masks*2*num; i++)
tk::dnn::writeBUF(buf, bias[i]);
// save classes names
for(int i=0; i<classes; i++) {
char tmp[YOLORT_CLASSNAME_W];
strcpy(tmp, classesNames[i].c_str());
for(int j=0; j<YOLORT_CLASSNAME_W; j++) {
tk::dnn::writeBUF(buf, tmp[j]);
}
}
}
int c, h, w;
int classes, num, n_masks;
float scaleXY;
std::vector<std::string> classesNames;
dnnType *mask;
dnnType *bias;
int entry_index(int batch, int location, int entry) {
int n = location / (w*h);
int loc = location % (w*h);
return batch*c*h*w + n*w*h*(4+classes+1) + entry*w*h + loc;
}
};
+77
View File
@@ -0,0 +1,77 @@
#include <tkdnn.h>
int testInference(std::vector<std::string> input_bins, std::vector<std::string> output_bins,
tk::dnn::Network *net, tk::dnn::NetworkRT *netRT = nullptr) {
std::vector<tk::dnn::Layer*> outputs;
for(int i=0; i<net->num_layers; i++) {
if(net->layers[i]->final)
outputs.push_back(net->layers[i]);
}
// no final layers, set last as output
if(outputs.size() == 0) {
outputs.push_back(net->layers[net->num_layers-1]);
}
// check input
if(input_bins.size() != 1) {
FatalError("currently support only 1 input");
}
if(output_bins.size() != outputs.size()) {
std::cout<<output_bins.size()<<" "<<outputs.size()<<"\n";
FatalError("outputs size missmatch");
}
// Load input
dnnType *data;
dnnType *input_h;
readBinaryFile(input_bins[0], net->input_dim.tot(), &input_h, &data);
// outputs
dnnType *cudnn_out[outputs.size()], *rt_out[outputs.size()];
tk::dnn::dataDim_t dim1 = net->input_dim; //input dim
printCenteredTitle(" CUDNN inference ", '=', 30); {
dim1.print();
TKDNN_TSTART
net->infer(dim1, data);
TKDNN_TSTOP
dim1.print();
}
for(int i=0; i<outputs.size(); i++) cudnn_out[i] = outputs[i]->dstData;
if(netRT != nullptr) {
tk::dnn::dataDim_t dim2 = net->input_dim;
printCenteredTitle(" TENSORRT inference ", '=', 30); {
dim2.print();
TKDNN_TSTART
netRT->infer(dim2, data);
TKDNN_TSTOP
dim2.print();
}
for(int i=0; i<outputs.size(); i++) rt_out[i] = (dnnType*)netRT->buffersRT[i+1];
}
int ret_cudnn = 0, ret_tensorrt = 0, ret_cudnn_tensorrt = 0;
for(int i=0; i<outputs.size(); i++) {
printCenteredTitle((std::string(" OUTPUT ") + std::to_string(i) + " CHECK RESULTS ").c_str(), '=', 30);
dnnType *out, *out_h;
int odim = outputs[i]->output_dim.tot();
readBinaryFile(output_bins[i], odim, &out_h, &out);
std::cout<<"CUDNN vs correct";
ret_cudnn |= checkResult(odim, cudnn_out[i], out) == 0 ? 0: ERROR_CUDNN;
if(netRT != nullptr) {
std::cout<<"TRT vs correct";
ret_tensorrt |= checkResult(odim, rt_out[i], out) == 0 ? 0 : ERROR_TENSORRT;
std::cout<<"CUDNN vs TRT ";
ret_cudnn_tensorrt |= checkResult(odim, cudnn_out[i], rt_out[i]) == 0 ? 0 : ERROR_CUDNNvsTENSORRT;
}
delete [] out_h;
checkCuda( cudaFree(out) );
}
delete [] input_h;
checkCuda( cudaFree(data) );
return ret_cudnn | ret_tensorrt | ret_cudnn_tensorrt;
}
+2 -10
View File
@@ -3,14 +3,6 @@
*/
#include "Network.h"
#include "Layer.h"
#include "NetworkRT.h"
namespace tkDNN {
/**
Return the tkDNN version
*/
int getVersion() {
return 100;
}
}
#define TKDNN_VERSION 500
+125
View File
@@ -0,0 +1,125 @@
#ifndef UTILS_H
#define UTILS_H
#include <iostream>
#include <sstream>
#include <fstream>
#include <iomanip>
#include <stdlib.h>
#include "cuda.h"
#include "cuda_runtime_api.h"
#include <cublas_v2.h>
#include <cudnn.h>
#include <unistd.h>
#include <ios>
#define dnnType float
// Colored output
#define COL_END "\033[0m"
#define COL_RED "\033[31m"
#define COL_GREEN "\033[32m"
#define COL_ORANGE "\033[33m"
#define COL_BLUE "\033[34m"
#define COL_PURPLE "\033[35m"
#define COL_CYAN "\033[36m"
#define COL_REDB "\033[1;31m"
#define COL_GREENB "\033[1;32m"
#define COL_ORANGEB "\033[1;33m"
#define COL_BLUEB "\033[1;34m"
#define COL_PURPLEB "\033[1;35m"
#define COL_CYANB "\033[1;36m"
#define TKDNN_VERBOSE 0
// Simple Timer
#define TKDNN_TSTART timespec start, end; \
clock_gettime(CLOCK_MONOTONIC, &start);
#define TKDNN_TSTOP_C(col, show) clock_gettime(CLOCK_MONOTONIC, &end); \
double t_ns = ((double)(end.tv_sec - start.tv_sec) * 1.0e9 + \
(double)(end.tv_nsec - start.tv_nsec))/1.0e6; \
if(show) std::cout<<col<<"Time:"<<std::setw(16)<<t_ns<<" ms\n"<<COL_END;
#define TKDNN_TSTOP TKDNN_TSTOP_C(COL_CYANB, TKDNN_VERBOSE)
/********************************************************
* Prints the error message, and exits
* ******************************************************/
#define EXIT_WAIVED 0
#define FatalError(s) { \
std::stringstream _where, _message; \
_where << __FILE__ << ':' << __LINE__; \
_message << std::string(s) + "\n" << __FILE__ << ':' << __LINE__;\
std::cerr << _message.str() << "\nAborting...\n"; \
cudaDeviceReset(); \
exit(EXIT_FAILURE); \
}
#define checkCUDNN(status) { \
std::stringstream _error; \
if (status != CUDNN_STATUS_SUCCESS) { \
_error << "CUDNN failure: " <<cudnnGetErrorString(status); \
FatalError(_error.str()); \
} \
}
#define checkCuda(status) { \
std::stringstream _error; \
if (status != 0) { \
_error << "Cuda failure: "<<cudaGetErrorString(status); \
FatalError(_error.str()); \
} \
}
#define checkERROR(status) { \
std::stringstream _error; \
if (status != 0) { \
_error << "Generic failure: " << status; \
FatalError(_error.str()); \
} \
}
#define checkNULL(ptr) { \
std::stringstream _error; \
if (ptr == nullptr) { \
_error << "Null pointer"; \
FatalError(_error.str()); \
} \
}
typedef enum {
ERROR_CUDNN = 2,
ERROR_TENSORRT = 4,
ERROR_CUDNNvsTENSORRT = 8
} resultError_t;
void printCenteredTitle(const char *title, char fill, int dim = 30);
bool fileExist(const char *fname);
void downloadWeightsifDoNotExist(const std::string& input_bin, const std::string& test_folder, const std::string& weights_url);
void readBinaryFile(std::string fname, int size, dnnType** data_h, dnnType** data_d, int seek = 0);
int checkResult(int size, dnnType *data_d, dnnType *correct_d, bool device = true, int limit = 10);
void printDeviceVector(int size, dnnType* vec_d, bool device = true);
float getColor(const int c, const int x, const int max);
void resize(int size, dnnType **data);
void matrixTranspose(cublasHandle_t handle, dnnType* srcData, dnnType* dstData, int rows, int cols);
void matrixMulAdd( cublasHandle_t handle, dnnType* srcData, dnnType* dstData,
dnnType* add_vector, int dim, dnnType mul);
void getMemUsage(double& vm_usage_kb, double& resident_set_kb);
void printCudaMemUsage();
void removePathAndExtension(const std::string &full_string, std::string &name);
static inline bool isCudaPointer(void *data) {
cudaPointerAttributes attr;
return cudaPointerGetAttributes(&attr, data) == 0;
}
#endif //UTILS_H
-73
View File
@@ -1,73 +0,0 @@
#ifndef UTILS_H
#define UTILS_H
#include <iostream>
#include <sstream>
#include <fstream>
#include <iomanip>
#include <stdlib.h>
#include "cuda.h"
#include "cuda_runtime_api.h"
#include <cublas_v2.h>
#include <cudnn.h>
#define value_type float
#define TIMER_START timespec start, end; \
clock_gettime(CLOCK_MONOTONIC, &start);
#define TIMER_STOP clock_gettime(CLOCK_MONOTONIC, &end); \
double t_ns = ((double)(end.tv_sec - start.tv_sec) * 1.0e9 + \
(double)(end.tv_nsec - start.tv_nsec))/1.0e6; \
std::cout<<"Time:"<<std::setw(16)<<t_ns<<" ms\n";
/********************************************************
* Prints the error message, and exits
* ******************************************************/
#define EXIT_WAIVED 0
#define FatalError(s) { \
std::stringstream _where, _message; \
_where << __FILE__ << ':' << __LINE__; \
_message << std::string(s) + "\n" << __FILE__ << ':' << __LINE__;\
std::cerr << _message.str() << "\nAborting...\n"; \
cudaDeviceReset(); \
exit(EXIT_FAILURE); \
}
#define checkCUDNN(status) { \
std::stringstream _error; \
if (status != CUDNN_STATUS_SUCCESS) { \
_error << "CUDNN failure: " <<cudnnGetErrorString(status); \
FatalError(_error.str()); \
} \
}
#define checkCuda(status) { \
std::stringstream _error; \
if (status != 0) { \
_error << "Cuda failure: "<<cudaGetErrorString(status); \
FatalError(_error.str()); \
} \
}
#define checkERROR(status) { \
std::stringstream _error; \
if (status != 0) { \
_error << "Generic failure: " << status; \
FatalError(_error.str()); \
} \
}
void readBinaryFile(const char* fname, int size, value_type** data_h, value_type** data_d);
void printDeviceVector(int size, value_type* vec_d);
void resize(int size, value_type **data);
void matrixTranspose(cublasHandle_t handle, value_type* srcData, value_type* dstData, int rows, int cols);
void matrixMulAdd( cublasHandle_t handle, value_type* srcData, value_type* dstData,
value_type* add_vector, int dim, value_type mul);
#endif //UTILS_H
+26
View File
@@ -0,0 +1,26 @@
#!/bin/bash
function elaborate_testset {
wget $1 -O $2.zip
unzip -d $2 $2.zip
rm $2.zip
cd $2/
realpath labels/* > all_labels.txt
realpath images/* > all_images.txt
cd ..
}
cd demo
for valset in $@
do
if [ $valset = "COCO" ]; then
echo "Downloading $valset validation set in demo"
elaborate_testset "https://cloud.hipert.unimore.it/s/LNxBDk4wzqXPL8c/download" "COCO_val2017"
elif [ $valset = "BDD" ]; then
echo "Downloading $valset validation set in demo"
elaborate_testset "https://cloud.hipert.unimore.it/s/bikqk3FzCq2tg4D/download" "BDD100K_val"
fi
done
+66
View File
@@ -0,0 +1,66 @@
#!/bin/bash
#based on https://devtalk.nvidia.com/default/topic/1042035/installing-opencv4-on-xavier/ & https://github.com/markste-in/OpenCV4XAVIER/blob/master/buildOpenCV4.sh
# Compute Capabilities can be found here https://developer.nvidia.com/cuda-gpus#compute
ARCH_BIN=7.2 # AGX Xavier
#ARCH_BIN=6.2 # Tx2
cd ~/Downloads
sudo apt-get install -y build-essential \
unzip \
pkg-config \
libjpeg-dev \
libpng-dev \
libtiff-dev \
libavcodec-dev \
libavformat-dev \
libswscale-dev \
libv4l-dev \
libxvidcore-dev \
libx264-dev \
libgtk-3-dev \
libatlas-base-dev \
gfortran \
python3-dev \
python3-venv \
libgstreamer1.0-dev \
libgstreamer-plugins-base1.0-dev \
libdc1394-22-dev \
libavresample-dev
git clone https://github.com/opencv/opencv.git
git clone https://github.com/opencv/opencv_contrib.git
python3 -m venv opencv4
source opencv4/bin/activate
pip install wheel
pip install numpy
cd opencv && mkdir build && cd build
cmake -D CMAKE_BUILD_TYPE=RELEASE \
-D CMAKE_INSTALL_PREFIX=/usr/local \
-D INSTALL_PYTHON_EXAMPLES=ON \
-D INSTALL_C_EXAMPLES=OFF \
-D OPENCV_EXTRA_MODULES_PATH='~/Downloads/opencv_contrib/modules' \
-D PYTHON_EXECUTABLE='~/Downloads/opencv4/bin/python' \
-D BUILD_EXAMPLES=ON \
-D WITH_CUDA=ON \
-D CUDA_ARCH_BIN=${ARCH_BIN} \
-D CUDA_ARCH_PTX="" \
-D ENABLE_FAST_MATH=ON \
-D CUDA_FAST_MATH=ON \
-D WITH_CUBLAS=ON \
-D WITH_LIBV4L=ON \
-D WITH_GSTREAMER=ON \
-D WITH_GSTREAMER_0_10=OFF \
-D WITH_TBB=ON \
../
make -j4
sudo make install
sudo ldconfig
cd ~/Downloads/opencv4/lib/python3.6/site-packages
ln -s /usr/local/lib/python3.6/site-packages/cv2.cpython-36m-aarch64-linux-gnu.so cv2.so
+97
View File
@@ -0,0 +1,97 @@
#!/bin/bash
cd build
RED='\033[1;31m'
GREEN='\033[1;32m'
ORANGE='\033[1;33m'
PINK='\033[1;95m'
NC='\033[0m' # No Color
function print_output {
if [ $1 -eq 0 ]; then
echo -e "$2 ${GREEN}OK${NC}"
elif [ $1 -eq 1 ]; then
echo -e "$2 ${RED}FATAL ERROR${NC}"
elif [ $1 -eq 2 ] || [ $1 -eq 10 ]; then
echo -e "$2 ${PINK}CUDNN ERROR${NC}"
elif [ $1 -eq 4 ] || [ $1 -eq 12 ]; then
echo -e "$2 ${PINK}TENSORRT ERROR${NC}"
elif [ $1 -eq 8 ]; then
echo -e "$2 ${PINK}CUDNN vs TENSORRT ERROR${NC}"
elif [ $1 -eq 6 ]; then
echo -e "$2 ${PINK}CUDNN & TENSORTRT ERROR${NC}"
elif [ $1 -eq 14 ]; then
echo -e "$2 ${PINK}ERROR FOR EVERY CHECK${NC}"
else
echo -e "$2 ${RED}NOT OKAY (OPENCV maybe)${NC}"
fi
}
out_file=results.log
rm $out_file
function test_net {
./test_$1 &>> $out_file
print_output $? $1
./test_rtinference $1*.rt $TKDNN_BATCHSIZE &>> $out_file
print_output $? "batched $1"
}
modes=( 1 ) # only FP32
# modes=( 1 2 ) # FP32 and FP16
# modes=( 1 2 3 ) # FP32, FP16 and INT8
for i in "${modes[@]}"
do
rm *rt
if [ $i -eq 1 ]
then
export TKDNN_MODE=FP32
echo -e "${ORANGE}Test FP32${NC}"
fi
if [ $i -eq 2 ]
then
export TKDNN_MODE=FP16
echo -e "${ORANGE}Test FP16${NC}"
fi
if [ $i -eq 3 ]
then
export TKDNN_MODE=INT8
export TKDNN_CALIB_LABEL_PATH=../demo/COCO_val2017/all_labels.txt
export TKDNN_CALIB_IMG_PATH=../demo/COCO_val2017/all_images.txt
echo -e "${ORANGE}Test INT8${NC}"
fi
export TKDNN_BATCHSIZE=2
echo -e "${ORANGE}Batch $TKDNN_BATCHSIZE ${NC}"
test_net mnist
./test_imuodom &>> $out_file
print_output $? imuodom
test_net yolo4
test_net yolo4_berkeley
test_net yolo4tiny
test_net yolo3
test_net yolo3_berkeley
test_net yolo3_coco4
test_net yolo3_flir
test_net yolo3_512
test_net yolo3tiny
test_net yolo3tiny_512
test_net yolo2
test_net yolo2_voc
#test_net yolo2tiny
test_net csresnext50-panet-spp
#test_net csresnext50-panet-spp_berkeley
test_net resnet101_cnet
test_net dla34_cnet
test_net mobilenetv2ssd
test_net mobilenetv2ssd512
test_net bdd-mobilenetv2ssd
done
echo "If errors occured, check logfile $out_file"
+42 -29
View File
@@ -3,55 +3,68 @@
#include "Layer.h"
#include "kernels.h"
namespace tkDNN {
namespace tk { namespace dnn {
Activation::Activation(Network *net, dataDim_t input_dim, cudnnActivationMode_t act_mode) :
Layer(net, input_dim) {
Activation::Activation(Network *net, int act_mode, const float ceiling) :
Layer(net) {
this->act_mode = act_mode;
checkCuda( cudaMalloc(&dstData, input_dim.tot()*sizeof(value_type)) );
this->ceiling = ceiling;
checkCuda( cudaMalloc(&dstData, input_dim.tot()*sizeof(dnnType)) );
checkCUDNN( cudnnSetTensor4dDescriptor(srcTensorDesc,
net->tensorFormat,
net->dataType,
input_dim.n*input_dim.l,
input_dim.c,
input_dim.h, input_dim.w) );
checkCUDNN( cudnnSetTensor4dDescriptor(dstTensorDesc,
if(int(act_mode) < 100) {
checkCUDNN( cudnnSetTensor4dDescriptor(srcTensorDesc,
net->tensorFormat,
net->dataType,
input_dim.n*input_dim.l,
input_dim.c,
input_dim.h, input_dim.w) );
checkCUDNN( cudnnSetTensor4dDescriptor(dstTensorDesc,
net->tensorFormat,
net->dataType,
input_dim.n*input_dim.l,
input_dim.c,
input_dim.h, input_dim.w) );
checkCUDNN( cudnnCreateActivationDescriptor(&activDesc) );
checkCUDNN( cudnnSetActivationDescriptor(activDesc,
act_mode,
CUDNN_PROPAGATE_NAN,
0.0) );
checkCUDNN( cudnnCreateActivationDescriptor(&activDesc) );
checkCUDNN( cudnnSetActivationDescriptor(activDesc,
(cudnnActivationMode_t) act_mode,
CUDNN_PROPAGATE_NAN,
ceiling) );
}
}
Activation::~Activation() {
checkCuda( cudaFree(dstData) );
checkCUDNN( cudnnDestroyActivationDescriptor(activDesc) );
if(int(act_mode) < 100)
checkCUDNN( cudnnDestroyActivationDescriptor(activDesc) );
}
value_type* Activation::infer(dataDim_t &dim, value_type* srcData) {
dnnType* Activation::infer(dataDim_t &dim, dnnType* srcData) {
if(act_mode == ACTIVATION_LEAKY) {
activationLEAKYForward(srcData, dstData, dim.tot());
value_type alpha = value_type(1);
value_type beta = value_type(0);
checkCUDNN( cudnnActivationForward(net->cudnnHandle,
activDesc,
&alpha,
srcTensorDesc,
srcData,
&beta,
dstTensorDesc,
dstData) );
}
else if(act_mode == ACTIVATION_MISH) {
activationMishForward(srcData, dstData, dim.tot());
} else {
dnnType alpha = dnnType(1);
dnnType beta = dnnType(0);
checkCUDNN( cudnnActivationForward(net->cudnnHandle,
activDesc,
&alpha,
srcTensorDesc,
srcData,
&beta,
dstTensorDesc,
dstData) );
}
return dstData;
}
}
}}
+56
View File
@@ -0,0 +1,56 @@
#include "BoundingBox.h"
namespace tk { namespace dnn {
float BoundingBox::overlap(const float p1, const float d1, const float p2, const float d2){
float l1 = p1 - d1/2;
float l2 = p2 - d2/2;
float left = l1 > l2 ? l1 : l2;
float r1 = p1 + d1/2;
float r2 = p2 + d2/2;
float right = r1 < r2 ? r1 : r2;
return right - left;
}
float BoundingBox::boxesIntersection(const BoundingBox &b){
float width = this->overlap(x, w, b.x, b.w);
float height = this->overlap(y, h, b.y, b.h);
if(width < 0 || height < 0)
return 0;
float area = width*height;
return area;
}
float BoundingBox::boxesUnion(const BoundingBox &b){
float i = this->boxesIntersection(b);
float u = w*h + b.w*b.h - i;
return u;
}
float BoundingBox::IoU(const BoundingBox &b){
float I = this->boxesIntersection(b);
float U = this->boxesUnion(b);
if (I == 0 || U == 0)
return 0;
return I / U;
}
void BoundingBox::clear(){
uniqueTruthIndex = -1;
truthFlag = 0;
maxIoU = 0;
}
std::ostream& operator<<(std::ostream& os, const BoundingBox& bb){
os <<"w: "<< bb.w << ", h: "<< bb.h << ", x: "<< bb.x << ", y: "<< bb.y <<
", cat: "<< bb.cl << ", conf: "<< bb.prob<< ", truth: "<<
bb.truthFlag<< ", assignedGT: "<< bb.uniqueTruthIndex<<
", maxIoU: "<< bb.maxIoU<<"\n";
return os;
}
bool boxComparison (const BoundingBox& a,const BoundingBox& b) {
return (a.prob>b.prob);
}
}}
+402
View File
@@ -0,0 +1,402 @@
#include "CenternetDetection.h"
namespace tk { namespace dnn {
bool CenternetDetection::init(const std::string& tensor_path, const int n_classes, const int n_batches){
std::cout<<(tensor_path).c_str()<<"\n";
netRT = new tk::dnn::NetworkRT(NULL, (tensor_path).c_str() );
classes = n_classes;
nBatches = n_batches;
dim = netRT->input_dim;
const char *coco_class_name[] = {
"person", "bicycle", "car", "motorcycle", "airplane",
"bus", "train", "truck", "boat", "traffic light", "fire hydrant",
"stop sign", "parking meter", "bench", "bird", "cat", "dog", "horse",
"sheep", "cow", "elephant", "bear", "zebra", "giraffe", "backpack",
"umbrella", "handbag", "tie", "suitcase", "frisbee", "skis",
"snowboard", "sports ball", "kite", "baseball bat", "baseball glove",
"skateboard", "surfboard", "tennis racket", "bottle", "wine glass",
"cup", "fork", "knife", "spoon", "bowl", "banana", "apple", "sandwich",
"orange", "broccoli", "carrot", "hot dog", "pizza", "donut", "cake",
"chair", "couch", "potted plant", "bed", "dining table", "toilet", "tv",
"laptop", "mouse", "remote", "keyboard", "cell phone", "microwave",
"oven", "toaster", "sink", "refrigerator", "book", "clock", "vase",
"scissors", "teddy bear", "hair drier", "toothbrush"
};
classesNames = std::vector<std::string>(coco_class_name, std::end( coco_class_name));
for(int c=0; c<classes; c++) {
int offset = c*123457 % classes;
float r = getColor(2, offset, classes);
float g = getColor(1, offset, classes);
float b = getColor(0, offset, classes);
colors[c] = cv::Scalar(int(255.0*b), int(255.0*g), int(255.0*r));
}
src = cv::Mat(cv::Size(2,3), CV_32F);
dst = cv::Mat(cv::Size(2,3), CV_32F);
dst2 = cv::Mat(cv::Size(2,3), CV_32F);
trans = cv::Mat(cv::Size(3,2), CV_32F);
trans2 = cv::Mat(cv::Size(3,2), CV_32F);
checkCuda(cudaMalloc(&input_d, sizeof(dnnType)*netRT->input_dim.tot() * nBatches));
dim_hm = tk::dnn::dataDim_t(1, 80, 128, 128, 1);
dim_wh = tk::dnn::dataDim_t(1, 2, 128, 128, 1);
dim_reg = tk::dnn::dataDim_t(1, 2, 128, 128, 1);
checkCuda( cudaMalloc(&topk_scores, dim_hm.c * K *sizeof(float)) );
checkCuda( cudaMalloc(&topk_inds_, dim_hm.c * K *sizeof(int)) );
checkCuda( cudaMalloc(&topk_ys_, dim_hm.c * K *sizeof(float)) );
checkCuda( cudaMalloc(&topk_xs_, dim_hm.c * K *sizeof(float)) );
checkCuda( cudaMalloc(&ids_d, dim_hm.c * dim_hm.h * dim_hm.w*sizeof(int)) );
checkCuda( cudaMalloc(&ids_2d, dim_hm.c * dim_hm.h * dim_hm.w*sizeof(int)) );
checkCuda( cudaMallocHost(&ids_, dim_hm.c * dim_hm.h * dim_hm.w*sizeof(int)) );
checkCuda( cudaMallocHost(&ids_2, dim_hm.c * dim_hm.h * dim_hm.w*sizeof(int)) );
for(int i =0; i<dim_hm.c * dim_hm.h * dim_hm.w; i++){
ids_[i] = i;
}
int val = 0;
for(int i =0; i <dim_hm.c * dim_hm.h * dim_hm.w; i++){
ids_2[i] = val;
if(i%dim_hm.c == 0)
val = 0;
}
checkCuda( cudaMallocHost(&scores, K *sizeof(float)) );
checkCuda( cudaMalloc(&scores_d, K *sizeof(float)) );
checkCuda( cudaMallocHost(&clses, K *sizeof(int)) );
checkCuda( cudaMalloc(&clses_d, K *sizeof(int)) );
checkCuda( cudaMalloc(&topk_inds_d, K *sizeof(int)) );
checkCuda( cudaMalloc(&topk_ys_d, K *sizeof(float)) );
checkCuda( cudaMalloc(&topk_xs_d, K *sizeof(float)) );
checkCuda( cudaMalloc(&inttopk_ys_d, K *sizeof(int)) );
checkCuda( cudaMalloc(&inttopk_xs_d, K *sizeof(int)) );
checkCuda( cudaMallocHost(&bbx0, K * sizeof(float)) );
checkCuda( cudaMallocHost(&bby0, K * sizeof(float)) );
checkCuda( cudaMallocHost(&bbx1, K * sizeof(float)) );
checkCuda( cudaMallocHost(&bby1, K * sizeof(float)) );
checkCuda( cudaMalloc(&bbx0_d, K * sizeof(float)) );
checkCuda( cudaMalloc(&bby0_d, K * sizeof(float)) );
checkCuda( cudaMalloc(&bbx1_d, K * sizeof(float)) );
checkCuda( cudaMalloc(&bby1_d, K * sizeof(float)) );
checkCuda( cudaMallocHost(&target_coords, 4 * K *sizeof(float)) );
#ifdef OPENCV_CUDACONTRIB
checkCuda( cudaMalloc(&mean_d, 3 * sizeof(float)) );
checkCuda( cudaMalloc(&stddev_d, 3 * sizeof(float)) );
float mean[3] = {0.408, 0.447, 0.47};
float stddev[3] = {0.289, 0.274, 0.278};
checkCuda(cudaMemcpy(mean_d, mean, 3*sizeof(float), cudaMemcpyHostToDevice));
checkCuda(cudaMemcpy(stddev_d, stddev, 3*sizeof(float), cudaMemcpyHostToDevice));
#else
checkCuda(cudaMallocHost(&input, sizeof(dnnType)*netRT->input_dim.tot()* nBatches));
mean << 0.408, 0.447, 0.47;
stddev << 0.289, 0.274, 0.278;
#endif
checkCuda( cudaMalloc(&d_ptrs, dim.c * dim.h*dim.w * sizeof(float)) );
// Alloc array used in the kernel
checkCuda( cudaMalloc(&src_out, K *sizeof(float)) );
checkCuda( cudaMalloc(&ids_out, K *sizeof(int)) );
dst2.at<float>(0,0)=width * 0.5;
dst2.at<float>(0,1)=width * 0.5;
dst2.at<float>(1,0)=width * 0.5;
dst2.at<float>(1,1)=width * 0.5 + width * -0.5;
dst2.at<float>(2,0)=dst2.at<float>(1,0) + (-dst2.at<float>(0,1)+dst2.at<float>(1,1) );
dst2.at<float>(2,1)=dst2.at<float>(1,1) + (dst2.at<float>(0,0)-dst2.at<float>(1,0) );
}
void CenternetDetection::preprocess(cv::Mat &frame, const int bi){
// -----------------------------------pre-process ------------------------------------------
// auto start_t = std::chrono::steady_clock::now();
// auto step_t = std::chrono::steady_clock::now();
// auto end_t = std::chrono::steady_clock::now();
cv::Size sz = originalSize[bi];
// std::cout<<"image: "<<sz.width<<", "<<sz.height<<std::endl;
cv::Size sz_old;
float scale = 1.0;
float new_height = sz.height * scale;
float new_width = sz.width * scale;
if(sz.height != sz_old.height && sz.width != sz_old.width){
float c[] = {new_width / 2.0f, new_height /2.0f};
float s[2];
if(sz.width > sz.height){
s[0] = sz.width * 1.0;
s[1] = sz.width * 1.0;
}
else{
s[0] = sz.height * 1.0;
s[1] = sz.height * 1.0;
}
// ----------- get_affine_transform
// rot_rad = pi * 0 / 100 --> 0
src.at<float>(0,0)=c[0];
src.at<float>(0,1)=c[1];
src.at<float>(1,0)=c[0];
src.at<float>(1,1)=c[1] + s[0] * -0.5;
dst.at<float>(0,0)=netRT->input_dim.w * 0.5;
dst.at<float>(0,1)=netRT->input_dim.h * 0.5;
dst.at<float>(1,0)=netRT->input_dim.w * 0.5;
dst.at<float>(1,1)=netRT->input_dim.h * 0.5 + netRT->input_dim.w * -0.5;
src.at<float>(2,0)=src.at<float>(1,0) + (-src.at<float>(0,1)+src.at<float>(1,1) );
src.at<float>(2,1)=src.at<float>(1,1) + (src.at<float>(0,0)-src.at<float>(1,0) );
dst.at<float>(2,0)=dst.at<float>(1,0) + (-dst.at<float>(0,1)+dst.at<float>(1,1) );
dst.at<float>(2,1)=dst.at<float>(1,1) + (dst.at<float>(0,0)-dst.at<float>(1,0) );
trans = cv::getAffineTransform( src, dst );
// end_t = std::chrono::steady_clock::now();
// std::cout << " TIME gett affine trans: " << std::chrono::duration_cast<std::chrono:: microseconds>(end_t - step_t).count() << " us" << std::endl;
// step_t = end_t;
trans2 = cv::getAffineTransform( dst2, src );
// end_t = std::chrono::steady_clock::now();
// std::cout << " TIME getAffineTrans 2: " << std::chrono::duration_cast<std::chrono:: microseconds>(end_t - step_t).count() << " us" << std::endl;
// step_t = end_t;
}
sz_old = sz;
#ifdef OPENCV_CUDACONTRIB
cv::cuda::GpuMat im_Orig;
cv::cuda::GpuMat imageF1_d, imageF2_d;
im_Orig = cv::cuda::GpuMat(frame);
cv::cuda::resize (im_Orig, imageF1_d, cv::Size(new_width, new_height));
checkCuda( cudaDeviceSynchronize() );
sz = imageF1_d.size();
// std::cout<<"size: "<<sz.height<<" "<<sz.width<<" - "<<std::endl;
// end_t = std::chrono::steady_clock::now();
// std::cout << " TIME resize: " << std::chrono::duration_cast<std::chrono:: microseconds>(end_t - step_t).count() << " us" << std::endl;
// step_t = end_t;
cv::cuda::warpAffine(imageF1_d, imageF2_d, trans, cv::Size(netRT->input_dim.w, netRT->input_dim.h), cv::INTER_LINEAR );
checkCuda( cudaDeviceSynchronize() );
imageF2_d.convertTo(imageF1_d, CV_32FC3, 1/255.0);
checkCuda( cudaDeviceSynchronize() );
// end_t = std::chrono::steady_clock::now();
// std::cout << " TIME convert: " << std::chrono::duration_cast<std::chrono:: microseconds>(end_t - step_t).count() << " us" << std::endl;
// step_t = end_t;
dim2 = dim;
cv::cuda::GpuMat bgr[3];
cv::cuda::split(imageF1_d,bgr);//split source
// end_t = std::chrono::steady_clock::now();
// std::cout << " TIME split: " << std::chrono::duration_cast<std::chrono:: microseconds>(end_t - step_t).count() << " us" << std::endl;
// step_t = end_t;
for(int i=0; i<dim.c; i++)
checkCuda( cudaMemcpy(d_ptrs + i*dim.h * dim.w, (float*)bgr[i].data, dim.h * dim.w * sizeof(float), cudaMemcpyDeviceToDevice) );
normalize(d_ptrs, dim.c, dim.h, dim.w, mean_d, stddev_d);
// end_t = std::chrono::steady_clock::now();
// std::cout << " TIME normalize: " << std::chrono::duration_cast<std::chrono:: microseconds>(end_t - step_t).count() << " us" << std::endl;
// step_t = end_t;
checkCuda(cudaMemcpy(input_d+ netRT->input_dim.tot()*bi, d_ptrs, dim2.tot()*sizeof(dnnType), cudaMemcpyDeviceToDevice));
// end_t = std::chrono::steady_clock::now();
// std::cout << " TIME Memcpy to input_d: " << std::chrono::duration_cast<std::chrono:: microseconds>(end_t - step_t).count() << " us" << std::endl;
// step_t = end_t;
#else
cv::Mat imageF;
resize(frame, imageF, cv::Size(new_width, new_height));
sz = imageF.size();
// std::cout<<"size: "<<sz.height<<" "<<sz.width<<" - "<<std::endl;
// end_t = std::chrono::steady_clock::now();
// std::cout << " TIME resize: " << std::chrono::duration_cast<std::chrono:: microseconds>(end_t - step_t).count() << " us" << std::endl;
// step_t = end_t;
cv::Mat trans = cv::getAffineTransform( src, dst );
cv::warpAffine(imageF, imageF, trans, cv::Size(netRT->input_dim.w, netRT->input_dim.h), cv::INTER_LINEAR );
// end_t = std::chrono::steady_clock::now();
// std::cout << " TIME warpAffine: " << std::chrono::duration_cast<std::chrono:: microseconds>(end_t - step_t).count() << " us" << std::endl;
// step_t = end_t;
sz = imageF.size();
// std::cout<<"size: "<<sz.height<<" "<<sz.width<<" - "<<std::endl;
imageF.convertTo(imageF, CV_32FC3, 1/255.0);
// end_t = std::chrono::steady_clock::now();
// std::cout << " TIME convertto: " << std::chrono::duration_cast<std::chrono:: microseconds>(end_t - step_t).count() << " us" << std::endl;
// step_t = end_t;
dim2 = dim;
//split channels
cv::Mat bgr[3];
cv::split(imageF,bgr);//split source
for(int i=0; i<3; i++){
bgr[i] = bgr[i] - mean[i];
bgr[i] = bgr[i] / stddev[i];
}
//write channels
for(int i=0; i<dim2.c; i++) {
int idx = i*imageF.rows*imageF.cols;
int ch = dim2.c-3 +i;
// std::cout<<"i: "<<i<<", idx: "<<idx<<", ch: "<<ch<<std::endl;
memcpy((void*)&input[idx+ netRT->input_dim.tot()*bi], (void*)bgr[ch].data, imageF.rows*imageF.cols*sizeof(dnnType));
}
checkCuda(cudaMemcpyAsync(input_d+ netRT->input_dim.tot()*bi, input+ netRT->input_dim.tot()*bi, dim2.tot()*sizeof(dnnType), cudaMemcpyHostToDevice));
#endif
}
void CenternetDetection::postprocess(const int bi, const bool mAP){
dnnType *rt_out[4];
rt_out[0] = (dnnType *)netRT->buffersRT[1]+ netRT->buffersDIM[1].tot()*bi;
rt_out[1] = (dnnType *)netRT->buffersRT[2]+ netRT->buffersDIM[2].tot()*bi;
rt_out[2] = (dnnType *)netRT->buffersRT[3]+ netRT->buffersDIM[3].tot()*bi;
rt_out[3] = (dnnType *)netRT->buffersRT[4]+ netRT->buffersDIM[4].tot()*bi;
// auto start_t = std::chrono::steady_clock::now();
// auto step_t = std::chrono::steady_clock::now();
// auto end_t = std::chrono::steady_clock::now();
// ------------------------------------ process --------------------------------------------
activationSIGMOIDForward(rt_out[0], rt_out[0], dim_hm.tot());
checkCuda( cudaDeviceSynchronize() );
subtractWithThreshold(rt_out[0], rt_out[0] + dim_hm.tot(), rt_out[1], rt_out[0], op);
// end_t = std::chrono::steady_clock::now();
// std::cout << " TIME threshold: " << std::chrono::duration_cast<std::chrono:: microseconds>(end_t - step_t).count() << " us" << std::endl;
// step_t = end_t;
// ----------- nms end
// ----------- topk
if(K > dim_hm.h * dim_hm.w){
printf ("Error topk (K is too large)\n");
return;
}
checkCuda( cudaMemcpy(ids_d, ids_, dim_hm.c * dim_hm.h * dim_hm.w*sizeof(int), cudaMemcpyHostToDevice) );
sort(rt_out[0],rt_out[0]+dim_hm.tot(),ids_d);
checkCuda( cudaDeviceSynchronize() );
// end_t = std::chrono::steady_clock::now();
// std::cout << " TIME sort: " << std::chrono::duration_cast<std::chrono:: microseconds>(end_t - step_t).count() << " us" << std::endl;
// step_t = end_t;
topk(rt_out[0], ids_d, K, scores_d, topk_inds_d, topk_ys_d, topk_xs_d);
checkCuda( cudaDeviceSynchronize() );
// end_t = std::chrono::steady_clock::now();
// std::cout << " TIME topk: " << std::chrono::duration_cast<std::chrono:: microseconds>(end_t - step_t).count() << " us" << std::endl;
// step_t = end_t;
checkCuda( cudaMemcpy(scores, scores_d, K *sizeof(float), cudaMemcpyDeviceToHost) );
topKxyclasses(topk_inds_d, topk_inds_d+K, K, width, dim_hm.w*dim_hm.h, clses_d, inttopk_xs_d, inttopk_ys_d);
// end_t = std::chrono::steady_clock::now();
// std::cout << " TIME topk x y clses 2: " << std::chrono::duration_cast<std::chrono:: microseconds>(end_t - step_t).count() << " us" << std::endl;
// step_t = end_t;
checkCuda( cudaMemcpy(topk_xs_d, (float *)inttopk_xs_d, K*sizeof(float), cudaMemcpyDeviceToDevice) );
checkCuda( cudaMemcpy(topk_ys_d, (float *)inttopk_ys_d, K*sizeof(float), cudaMemcpyDeviceToDevice) );
checkCuda( cudaMemcpy(clses, clses_d, K*sizeof(int), cudaMemcpyDeviceToHost) );
// ----------- topk end
topKxyAddOffset(topk_inds_d, K, dim_reg.h*dim_reg.w, inttopk_xs_d, inttopk_ys_d, topk_xs_d, topk_ys_d, rt_out[3], src_out, ids_out);
// checkCuda( cudaDeviceSynchronize() );
// end_t = std::chrono::steady_clock::now();
// std::cout << " TIME add offset: " << std::chrono::duration_cast<std::chrono:: microseconds>(end_t - step_t).count() << " us" << std::endl;
// step_t = end_t;
bboxes(topk_inds_d, K, dim_wh.h*dim_wh.w, topk_xs_d, topk_ys_d, rt_out[2], bbx0_d, bbx1_d, bby0_d, bby1_d, src_out, ids_out);
// checkCuda( cudaDeviceSynchronize() );
checkCuda( cudaMemcpy(bbx0, bbx0_d, K * sizeof(float), cudaMemcpyDeviceToHost) );
checkCuda( cudaMemcpy(bby0, bby0_d, K * sizeof(float), cudaMemcpyDeviceToHost) );
checkCuda( cudaMemcpy(bbx1, bbx1_d, K * sizeof(float), cudaMemcpyDeviceToHost) );
checkCuda( cudaMemcpy(bby1, bby1_d, K * sizeof(float), cudaMemcpyDeviceToHost) );
// end_t = std::chrono::steady_clock::now();
// std::cout << " TIME bboxes: " << std::chrono::duration_cast<std::chrono:: microseconds>(end_t - step_t).count() << " us" << std::endl;
// step_t = end_t;
// ---------------------------------- post-process -----------------------------------------
// --------- ctdet_post_process
// --------- transform_preds
cv::Mat new_pt1(cv::Size(1,2), CV_32F);
cv::Mat new_pt2(cv::Size(1,2), CV_32F);
for(int i = 0; i<K; i++){
new_pt1.at<float>(0,0)=static_cast<float>(trans2.at<double>(0,0))*bbx0[i] +
static_cast<float>(trans2.at<double>(0,1))*bby0[i] +
static_cast<float>(trans2.at<double>(0,2))*1.0;
new_pt1.at<float>(0,1)=static_cast<float>(trans2.at<double>(1,0))*bbx0[i] +
static_cast<float>(trans2.at<double>(1,1))*bby0[i] +
static_cast<float>(trans2.at<double>(1,2))*1.0;
new_pt2.at<float>(0,0)=static_cast<float>(trans2.at<double>(0,0))*bbx1[i] +
static_cast<float>(trans2.at<double>(0,1))*bby1[i] +
static_cast<float>(trans2.at<double>(0,2))*1.0;
new_pt2.at<float>(0,1)=static_cast<float>(trans2.at<double>(1,0))*bbx1[i] +
static_cast<float>(trans2.at<double>(1,1))*bby1[i] +
static_cast<float>(trans2.at<double>(1,2))*1.0;
target_coords[i*4] = new_pt1.at<float>(0,0);
target_coords[i*4+1] = new_pt1.at<float>(0,1);
target_coords[i*4+2] = new_pt2.at<float>(0,0);
target_coords[i*4+3] = new_pt2.at<float>(0,1);
}
detected.clear();
for(int i = 0; i<classes; i++){
for(int j=0; j<K; j++)
if(clses[j] == i){
if(scores[j] > confThreshold){
// std::cout<<"th: "<<scores[j]<<" - cl: "<<clses[j]<<" i: "<<i<<std::endl;
//add coco bbox
//det[0:4], i, det[4]
int x0 = target_coords[j*4];
int y0 = target_coords[j*4+1];
int x1 = target_coords[j*4+2];
int y1 = target_coords[j*4+3];
int obj_class = clses[j];
float prob = scores[j];
// std::cout<<"("<<x0<<", "<<y0<<"),("<<x1<<", "<<y1<<")"<<std::endl;
tk::dnn::box res;
res.cl = obj_class;
res.prob = prob;
res.x = x0;
res.y = y0;
res.w = x1 - x0;
res.h = y1 - y0;
detected.push_back(res);
}
}
}
batchDetected.push_back(detected);
// end_t = std::chrono::steady_clock::now();
// std::cout << " TIME detections: " << std::chrono::duration_cast<std::chrono:: microseconds>(end_t - step_t).count() << " us" << std::endl;
// step_t = end_t;
}
}}
+164 -66
View File
@@ -2,83 +2,181 @@
#include "Layer.h"
namespace tkDNN {
namespace tk { namespace dnn {
Conv2d::Conv2d( Network *net, dataDim_t in_dim, int out_ch,
int kernelH, int kernelW, int strideH, int strideW,
const char* fname_weights, const char* fname_bias) :
LayerWgs(net, in_dim, in_dim.c, out_ch, kernelH, kernelW, 1,
fname_weights, fname_bias) {
void Conv2d::initCUDNN(bool back) {
this->kernelH = kernelH;
this->kernelW = kernelW;
this->strideH = strideH;
this->strideW = strideW;
cudnnTensorDescriptor_t srcTensor = srcTensorDesc;
cudnnTensorDescriptor_t dstTensor = dstTensorDesc;
dataDim_t idim, odim;
if(!back) {
idim = input_dim;
odim = output_dim;
} else {
idim = output_dim;
odim = input_dim;
}
checkCUDNN( cudnnCreateFilterDescriptor(&filterDesc) );
checkCUDNN( cudnnCreateConvolutionDescriptor(&convDesc) );
checkCUDNN( cudnnCreateTensorDescriptor(&biasTensorDesc) );
int n = input_dim.n;
int c = input_dim.c;
int h = input_dim.h;
int w = input_dim.w;
checkCUDNN( cudnnSetTensor4dDescriptor(srcTensorDesc,
net->tensorFormat, net->dataType, n, c, h, w) );
// input tensor dim
checkCUDNN( cudnnSetTensor4dDescriptor(srcTensor,
net->tensorFormat, net->dataType, idim.n, idim.c, idim.h, idim.w) );
checkCUDNN( cudnnSetFilter4dDescriptor(filterDesc,
net->dataType, net->tensorFormat, out_ch, input_dim.c,
kernelH, kernelW) );
net->dataType, net->tensorFormat, odim.c, idim.c/groups,
kernelH, kernelW) );
checkCUDNN( cudnnSetConvolution2dDescriptor(convDesc,
0,0, // padding
strideH, strideW, // stride
1,1, // upscale
CUDNN_CROSS_CORRELATION) );
paddingH, paddingW, // padding
strideH, strideW, // stride
1,1, // upscale
CUDNN_CROSS_CORRELATION, CUDNN_DATA_FLOAT) );
// find dimension of convolution output
checkCUDNN( cudnnSetConvolutionGroupCount(convDesc,
groups) );
// check dimension of convolution output
dataDim_t tmpdim;
checkCUDNN( cudnnGetConvolution2dForwardOutputDim(
convDesc, srcTensorDesc, filterDesc,
&n, &c, &h, &w) );
convDesc, srcTensor, filterDesc,
&tmpdim.n, &tmpdim.c, &tmpdim.h, &tmpdim.w) );
checkCUDNN( cudnnSetTensor4dDescriptor(dstTensorDesc,
net->tensorFormat, net->dataType, n, c, h, w) );
checkCUDNN( cudnnGetConvolutionForwardAlgorithm(net->cudnnHandle,
srcTensorDesc, filterDesc, convDesc, dstTensorDesc,
CUDNN_CONVOLUTION_FWD_PREFER_FASTEST, 0, &algo) );
if(odim.n != tmpdim.n || odim.c != tmpdim.c || odim.h != tmpdim.h || odim.w != tmpdim.w) {
std::cout<<"tkdim input: "; idim.print();
std::cout<<"tkdim output: "; odim.print();
std::cout<<"cudnndim: "; tmpdim.print();
FatalError("Error conv dimension mismatch");
}
checkCUDNN( cudnnSetTensor4dDescriptor(dstTensor,
net->tensorFormat, net->dataType, odim.n, odim.c, odim.h, odim.w) );
checkCUDNN( cudnnSetTensor4dDescriptor(biasTensorDesc,
net->tensorFormat, net->dataType,
1, output_dim.c, 1, 1) );
// init workspace
workSpace = NULL;
ws_sizeInBytes = 0;
int algo_count = 0;
if(back) {
checkCUDNN( cudnnGetConvolutionBackwardDataAlgorithm_v7(net->cudnnHandle,
filterDesc, dstTensor, convDesc, srcTensor, 1, &algo_count, &bwAlgo) );
checkCUDNN(cudnnGetConvolutionBackwardDataWorkspaceSize(net->cudnnHandle,
filterDesc, dstTensor, convDesc, srcTensor,
bwAlgo.algo, &ws_sizeInBytes));
checkCUDNN( cudnnGetConvolutionForwardWorkspaceSize(net->cudnnHandle,
srcTensorDesc, filterDesc, convDesc, dstTensorDesc,
algo, &ws_sizeInBytes) );
// invert tensors
srcTensorDesc = dstTensor;
dstTensorDesc = srcTensor;
} else {
checkCUDNN( cudnnGetConvolutionForwardAlgorithm_v7(net->cudnnHandle,
srcTensor, filterDesc, convDesc, dstTensor,
1, &algo_count, &algo) );
checkCUDNN(cudnnGetConvolutionForwardWorkspaceSize(net->cudnnHandle,
srcTensor, filterDesc, convDesc, dstTensor,
algo.algo, &ws_sizeInBytes));
}
if(algo_count < 1)
FatalError("Cannot retrieve convolutional algo");
}
void Conv2d::inferCUDNN(dnnType* srcData, bool back) {
dnnType alpha = dnnType(1);
dnnType beta = dnnType(0);
if(back) {
checkCUDNN(cudnnConvolutionBackwardData(net->cudnnHandle,
&alpha, filterDesc, data_d,
srcTensorDesc, srcData,
convDesc, bwAlgo.algo, workSpace, ws_sizeInBytes,
&beta, dstTensorDesc, dstData));
} else {
checkCUDNN(cudnnConvolutionForward(net->cudnnHandle,
&alpha, srcTensorDesc, srcData, filterDesc,
data_d, convDesc, algo.algo, workSpace, ws_sizeInBytes,
&beta, dstTensorDesc, dstData));
}
if(!batchnorm && !additional_bias) { //CHECK WITH IF CORRECT
// bias
alpha = dnnType(1);
beta = dnnType(1);
checkCUDNN( cudnnAddTensor(net->cudnnHandle,
&alpha, biasTensorDesc, bias_d,
&beta, dstTensorDesc, dstData) );
} else {
if(additional_bias)
{
alpha = dnnType(1);
beta = dnnType(1);
checkCUDNN( cudnnAddTensor(net->cudnnHandle,
&alpha, biasTensorDesc, bias2_d,
&beta, dstTensorDesc, dstData) );
}
if(batchnorm)
{
alpha = dnnType(1);
beta = dnnType(0);
checkCUDNN( cudnnBatchNormalizationForwardInference(net->cudnnHandle,
CUDNN_BATCHNORM_SPATIAL, &alpha, &beta,
dstTensorDesc, dstData, dstTensorDesc,
dstData, biasTensorDesc, //same tensor descriptor as bias
scales_d, bias_d, mean_d, variance_d,
TKDNN_BN_MIN_EPSILON) );
}
}
}
Conv2d::Conv2d( Network *net, int out_ch, int kernelH, int kernelW,
int strideH, int strideW, int paddingH, int paddingW,
std::string fname_weights, bool batchnorm, bool deConv, int groups, bool additional_bias) :
LayerWgs(net, net->getOutputDim().c, out_ch, kernelH, kernelW, 1,
fname_weights, batchnorm, additional_bias, deConv, groups) {
this->kernelH = kernelH;
this->kernelW = kernelW;
this->strideH = strideH;
this->strideW = strideW;
this->paddingH = paddingH;
this->paddingW = paddingW;
this->deConv = deConv;
this->groups = groups;
this->additional_bias = additional_bias;
if(!deConv) {
output_dim.n = input_dim.n;
output_dim.c = out_ch;
output_dim.h = (input_dim.h + 2 * paddingH - kernelH) / strideH + 1;
output_dim.w = (input_dim.w + 2 * paddingW - kernelW) / strideW + 1;
output_dim.l = 1;
} else {
output_dim.n = input_dim.n;
output_dim.c = out_ch;
output_dim.h = ((input_dim.h-1) * strideH) - 2*paddingH + kernelH;
output_dim.w = ((input_dim.w-1) * strideW) - 2*paddingW + kernelW;
output_dim.l = 1;
}
initCUDNN(deConv);
// allocate warkspace
if (ws_sizeInBytes!=0) {
checkCuda( cudaMalloc(&workSpace, ws_sizeInBytes) );
}
checkCUDNN( cudnnSetTensor4dDescriptor(biasTensorDesc,
net->tensorFormat, net->dataType,
1, out_ch, 1, 1) );
output_dim.n = n;
output_dim.c = c;
output_dim.h = h;
output_dim.w = w;
output_dim.l = 1;
//allocate data for infer result
checkCuda( cudaMalloc(&dstData, output_dim.tot()*sizeof(value_type)) );
checkCuda( cudaMalloc(&dstData, output_dim.tot()*sizeof(dnnType)) );
}
Conv2d::~Conv2d() {
checkCUDNN( cudnnDestroyFilterDescriptor(filterDesc) );
checkCUDNN( cudnnDestroyConvolutionDescriptor(convDesc) );
checkCUDNN( cudnnDestroyTensorDescriptor(biasTensorDesc) );
@@ -89,28 +187,28 @@ Conv2d::~Conv2d() {
checkCuda( cudaFree(dstData) );
}
value_type* Conv2d::infer(dataDim_t &dim, value_type* srcData) {
dnnType* Conv2d::infer(dataDim_t &dim, dnnType* srcData) {
if(deConv) {
FatalError("you must use DeConv class for Deconvolutional layers");
}
// convolution
value_type alpha = value_type(1);
value_type beta = value_type(0);
checkCUDNN( cudnnConvolutionForward(net->cudnnHandle,
&alpha, srcTensorDesc, srcData, filterDesc,
data_d, convDesc, algo, workSpace, ws_sizeInBytes,
&beta, dstTensorDesc, dstData) );
// bias
alpha = value_type(1);
beta = value_type(1);
checkCUDNN( cudnnAddTensor(net->cudnnHandle,
&alpha, biasTensorDesc, bias_d,
&beta, dstTensorDesc, dstData) );
inferCUDNN(srcData, false);
//update data dimensions
dim = output_dim;
return dstData;
}
dnnType* DeConv2d::infer(dataDim_t &dim, dnnType* srcData) {
// convolution
inferCUDNN(srcData, true);
//update data dimensions
dim = output_dim;
return dstData;
}
}}
+263
View File
@@ -0,0 +1,263 @@
#include "tkDNN/DarknetParser.h"
namespace tk { namespace dnn {
std::string darknetParseType(const std::string& line){
size_t start = line.find("[");
size_t end = line.find("]");
if( start == std::string::npos || end == std::string::npos)
return "";
start++;
std::string type = line.substr(start, end-start);
return type;
}
bool divideNameAndValue(const std::string& line, std::string&name, std::string& value){
size_t sep = line.find("=");
if(sep == std::string::npos)
return false;
name = line.substr(0, sep);
value = line.substr(sep+1, line.size() - (sep+1));
return true;
}
std::vector<int> fromStringToIntVec(const std::string& line, const char delimiter){
std::stringstream linestream(line);
std::string value;
std::vector<int> values;
while(getline(linestream,value,delimiter))
values.push_back(std::stoi(value));
return values;
}
bool darknetParseFields(const std::string& line, darknetFields_t& fields){
std::string name,value;
if(!divideNameAndValue(line, name, value))
return false;
if(name.find("width") != std::string::npos)
fields.width = std::stoi(value);
else if(name.find("height") != std::string::npos)
fields.height = std::stoi(value);
else if(name.find("channels") != std::string::npos)
fields.channels = std::stoi(value);
else if(name.find("batch_normalize") != std::string::npos)
fields.batch_normalize = std::stoi(value);
else if(name.find("filters") != std::string::npos)
fields.filters = std::stoi(value);
else if(name.find("activation") != std::string::npos)
fields.activation = value;
else if(name.find("size") != std::string::npos){
fields.size_x = std::stoi(value);
fields.size_y = std::stoi(value);
}
else if(name.find("size_x") != std::string::npos)
fields.size_x = std::stoi(value);
else if(name.find("size_y") != std::string::npos)
fields.size_y = std::stoi(value);
else if(name.find("stride") != std::string::npos){
fields.stride_x = std::stoi(value);
fields.stride_y = std::stoi(value);
}
else if(name.find("stride_x") != std::string::npos)
fields.stride_x = std::stoi(value);
else if(name.find("stride_y") != std::string::npos)
fields.stride_y = std::stoi(value);
else if(name.find("pad") != std::string::npos)
fields.pad = std::stoi(value);
else if(name.find("classes") != std::string::npos)
fields.classes = std::stoi(value);
else if(name.find("num") != std::string::npos)
fields.num = std::stoi(value);
else if(name.find("coords") != std::string::npos)
fields.coords = std::stoi(value);
else if(name.find("groups") != std::string::npos)
fields.groups = std::stoi(value);
else if(name.find("group_id") != std::string::npos)
fields.group_id = std::stoi(value);
else if(name.find("scale_x_y") != std::string::npos)
fields.scale_xy = std::stof(value);
else if(name.find("from") != std::string::npos)
fields.layers.push_back(std::stof(value));
else if(name.find("mask") != std::string::npos){
auto vec = fromStringToIntVec(value, ',');
fields.n_mask = vec.size();
}
else if(name.find("layers") != std::string::npos)
fields.layers = fromStringToIntVec(value, ',');
else
std::cout<<"Not supported field: "<<line<<std::endl;
return true;
}
tk::dnn::Network *darknetAddNet(darknetFields_t &fields) {
//std::cout<<"Add Net: "<<fields.type<<"\n";
dataDim_t dim(1, fields.channels, fields.height, fields.width);
return new tk::dnn::Network(dim);
}
void darknetAddLayer(tk::dnn::Network *net, darknetFields_t &f, std::string wgs_path, std::vector<tk::dnn::Layer*> &netLayers, const std::vector<std::string>& names) {
if(net == nullptr)
FatalError("Cant add a layer without a Net\n");
// padding compute
if(f.pad == 1) {
f.padding_x = f.padding_y = f.size_x /2;
}
//std::cout<<"Add layer: "<<f.type<<"\n";
if(f.type == "convolutional") {
std::string wgs = wgs_path + "/c" + std::to_string(netLayers.size()) + ".bin";
//printf("%d (%d,%d) (%d,%d) (%d,%d) %s %d %d\n", f.filters, f.size_x, f.size_y, f.stride_x, f.stride_y, f.padding_x, f.padding_y, wgs.c_str(), f.batch_normalize, f.groups);
tk::dnn::Conv2d *l= new tk::dnn::Conv2d(net, f.filters, f.size_x, f.size_y, f.stride_x,
f.stride_y, f.padding_x, f.padding_y, wgs, f.batch_normalize, false, f.groups);
netLayers.push_back(l);
} else if(f.type == "maxpool") {
if(f.stride_x == 1 && f.stride_y == 1)
netLayers.push_back(new tk::dnn::Pooling(net, f.size_x, f.size_y, f.stride_x, f.stride_y,
f.padding_x, f.padding_y, tk::dnn::POOLING_MAX_FIXEDSIZE));
else
netLayers.push_back(new tk::dnn::Pooling(net, f.size_x, f.size_y, f.stride_x, f.stride_y,
f.padding_x, f.padding_y, tk::dnn::POOLING_MAX));
} else if(f.type == "avgpool") {
netLayers.push_back(new tk::dnn::Pooling(net, f.size_x, f.size_y, f.stride_x, f.stride_y,
f.padding_x, f.padding_y, tk::dnn::POOLING_AVERAGE));
} else if(f.type == "shortcut") {
if(f.layers.size() != 1) FatalError("no layers to shortcut\n");
int layerIdx = f.layers[0];
if(layerIdx < 0)
layerIdx = netLayers.size() + layerIdx;
if(layerIdx < 0 || layerIdx >= netLayers.size()) FatalError("impossible to shortcut\n");
//std::cout<<"shortcut to "<<layerIdx<<" "<<netLayers[layerIdx]->getLayerName()<<"\n";
netLayers.push_back(new tk::dnn::Shortcut(net, netLayers[layerIdx]));
} else if(f.type == "upsample") {
netLayers.push_back(new tk::dnn::Upsample(net, f.stride_x));
} else if(f.type == "route") {
if(f.layers.size() == 0) FatalError("no layers to Route\n");
std::vector<tk::dnn::Layer*> layers;
for(int i=0; i<f.layers.size(); i++) {
int layerIdx = f.layers[i];
if(layerIdx < 0)
layerIdx = netLayers.size() + layerIdx;
if(layerIdx < 0 || layerIdx >= netLayers.size()) FatalError("impossible to route\n");
//std::cout<<"Route to "<<layerIdx<<" "<<netLayers[layerIdx]->getLayerName()<<"\n";
layers.push_back(netLayers[layerIdx]);
}
netLayers.push_back(new tk::dnn::Route(net, layers.data(), layers.size(), f.groups, f.group_id));
} else if(f.type == "reorg") {
netLayers.push_back(new tk::dnn::Reorg(net, f.stride_x));
} else if(f.type == "region") {
netLayers.push_back(new tk::dnn::Region(net, f.classes, f.coords, f.num));
} else if(f.type == "yolo") {
std::string wgs = wgs_path + "/g" + std::to_string(netLayers.size()) + ".bin";
//printf("%d %d %s %d %f\n", f.classes, f.num/f.n_mask, wgs.c_str(), f.n_mask, f.scale_xy);
tk::dnn::Yolo *l = new tk::dnn::Yolo(net, f.classes, f.num/f.n_mask, wgs, f.n_mask, f.scale_xy);
if(names.size() != f.classes)
FatalError("Mismatch between number of classes and names");
l->classesNames = names;
netLayers.push_back(l);
} else{
FatalError("layer not supported: " + f.type);
}
// add activation
if(netLayers.size() > 0 && f.activation != "linear") {
tkdnnActivationMode_t act;
if(f.activation == "relu") act = tkdnnActivationMode_t(CUDNN_ACTIVATION_RELU);
else if(f.activation == "leaky") act = tk::dnn::ACTIVATION_LEAKY;
else if(f.activation == "mish") act = tk::dnn::ACTIVATION_MISH;
else { FatalError("activation not supported: " + f.activation); }
netLayers[netLayers.size()-1] = new tk::dnn::Activation(net, act);
};
}
std::vector<std::string> darknetReadNames(const std::string& names_file){
std::ifstream if_names(names_file);
if(!if_names.is_open())
FatalError("cloud not open names file: " + names_file);
std::vector<std::string> names;
std::string line;
while(std::getline(if_names, line))
if(line != "")
names.push_back(line);
if_names.close();
return names;
}
tk::dnn::Network* darknetParser(const std::string& cfg_file, const std::string& wgs_path, const std::string& names_file) {
tk::dnn::Network *net = nullptr;
// layers without activations to retrive correct id number
std::vector<tk::dnn::Layer*> netLayers;
std::ifstream if_cfg(cfg_file);
if(!if_cfg.is_open())
FatalError("cloud not open cfg file: " + cfg_file);
std::vector<std::string> names = darknetReadNames(names_file);
darknetFields_t fields; // will be filled with layers fields
std::string line;
while(std::getline(if_cfg, line)) {
// remove comments
std::size_t found = line.find("#");
if ( found != std::string::npos ) {
line = line.substr(0, found);
}
// skip empty lines
if(line.size() == 0)
continue;
std::string type = darknetParseType(line);
if(type.size() > 0) {
// end of filled type
if(fields.type != "") {
if(fields.type == "net")
net = darknetAddNet(fields);
else
darknetAddLayer(net, fields, wgs_path, netLayers, names);
}
// new type
//std::cout<<"type: "<<type<<"\n";
fields = darknetFields_t(); // reset to default
fields.type = type;
continue;
}
if(darknetParseFields(line, fields)) {
// already parsed do nothing
} else {
FatalError("could not parse line: " + line);
}
}
// end of filled type
if(fields.type != "") {
darknetAddLayer(net, fields, wgs_path, netLayers, names);
}
if(net == nullptr) {
FatalError("net not found\n");
}
return net;
}
}}
+142
View File
@@ -0,0 +1,142 @@
#include <iostream>
#include "Layer.h"
#include "kernels.h"
#include <math.h>
namespace tk { namespace dnn {
void DeformConv2d::initCUDNN() {
stat = cublasCreate(&handle);
if (stat != CUBLAS_STATUS_SUCCESS)
FatalError("CUBLAS initialization failed\n");
checkCUDNN( cudnnCreateTensorDescriptor(&biasTensorDesc) );
checkCUDNN( cudnnSetTensor4dDescriptor(biasTensorDesc,
net->tensorFormat, net->dataType,
1, output_dim.c, 1, 1) );
checkCUDNN( cudnnSetTensor4dDescriptor(dstTensorDesc,
net->tensorFormat, net->dataType, output_dim.n, output_dim.c, output_dim.h, output_dim.w));
const int height_ones = (preconv->input_dim.h + 2 * this->paddingH - (1 * (this->kernelH - 1) + 1)) / this->strideH + 1;
const int width_ones = (preconv->input_dim.w + 2 * this->paddingW - (1 * (this->kernelW - 1) + 1)) / this->strideW + 1;
const int dim_ones = preconv->input_dim.c * this->kernelH * this->kernelW * 1 * height_ones * width_ones;
int dst_dim = preconv->output_dim.tot();
if( dst_dim % 3 != 0 )
FatalError("DeformConv2d: the Conv2d output is not divisible by three");
chunk_dim = dst_dim/3;
checkCuda( cudaMalloc(&offset, 2*chunk_dim*sizeof(dnnType)));
checkCuda( cudaMalloc(&mask, chunk_dim*sizeof(dnnType)));
// kernel ones
checkCuda( cudaMalloc(&ones_d1, (height_ones*width_ones)*sizeof(dnnType)) );
dnnType *ones_h1;
checkCuda( cudaMallocHost(&ones_h1, (height_ones*width_ones)*sizeof(dnnType)) );
for(int i=0; i<height_ones*width_ones; i++)
ones_h1[i]=1.0f;
checkCuda( cudaMemcpy(ones_d1, ones_h1, (height_ones*width_ones)*sizeof(dnnType), cudaMemcpyHostToDevice) );
checkCuda( cudaFreeHost(ones_h1) );
checkCuda( cudaMalloc(&ones_d2, dim_ones*sizeof(dnnType)) );
dnnType *ones_h2;
checkCuda( cudaMallocHost(&ones_h2, dim_ones*sizeof(dnnType)) );
for(int i=0; i<dim_ones; i++)
ones_h2[i]=1.0f;
checkCuda( cudaMemcpy(ones_d2, ones_h2, (dim_ones)*sizeof(dnnType), cudaMemcpyHostToDevice) );
checkCuda( cudaFreeHost(ones_h2) );
checkCuda( cudaDeviceSynchronize() );
}
DeformConv2d::DeformConv2d( Network *net, int out_ch, int deformable_group, int kernelH, int kernelW,
int strideH, int strideW, int paddingH, int paddingW,
std::string d_fname_weights, std::string fname_weights, bool batchnorm) :
LayerWgs(net, net->getOutputDim().c, out_ch, kernelH, kernelW, 1,
d_fname_weights, batchnorm, true) {
this->out_ch = out_ch;
this->deformableGroup = deformable_group;
this->kernelH = kernelH;
this->kernelW = kernelW;
this->strideH = strideH;
this->strideW = strideW;
this->paddingH = paddingH;
this->paddingW = paddingW;
preconv = new tk::dnn::Conv2d(net, deformable_group * 3 * kernelH * kernelW, kernelH, kernelW,
strideH, strideW, paddingH, paddingW, fname_weights, false);
net->num_layers--;
output_dim = preconv->output_dim;
output_dim.c = out_ch;
initCUDNN();
//allocate data for infer result
checkCuda( cudaMalloc(&dstData, output_dim.tot()*sizeof(dnnType)) );
}
DeformConv2d::~DeformConv2d() {
checkCUDNN( cudnnDestroyTensorDescriptor(biasTensorDesc) );
checkCuda( cudaFree(dstData) );
checkCuda( cudaFree(ones_d1) );
checkCuda( cudaFree(ones_d2) );
checkCuda( cudaFree(offset) );
checkCuda( cudaFree(mask) );
checkCuda( cudaFree(output_conv) );
cublasDestroy(handle);
}
dnnType* DeformConv2d::infer(dataDim_t &dim, dnnType* srcData) {
// conv2d
output_conv = preconv->infer(dim, srcData);
// split conv2d outputs into offset and mask
checkCuda(cudaMemcpy(offset, output_conv, 2*chunk_dim*sizeof(dnnType), cudaMemcpyDeviceToDevice));
checkCuda(cudaMemcpy(mask, output_conv + 2*chunk_dim, chunk_dim*sizeof(dnnType), cudaMemcpyDeviceToDevice));
// kernel sigmoide
activationSIGMOIDForward(mask, mask, chunk_dim);
// deformable convolution
dcnV2CudaForward(stat, handle,
srcData, this->data_d,
this->bias2_d, ones_d1,
offset, mask,
dstData, ones_d2,
this->kernelH, this->kernelW,
this->strideH, this->strideW,
this->paddingH, this->paddingW,
1, 1,
this->deformableGroup, 0, //batch_id for cudnn is set to 0 (no batch)
preconv->input_dim.n, preconv->input_dim.c, preconv->input_dim.h, preconv->input_dim.w,
this->output_dim.n, this->output_dim.c, this->output_dim.h, this->output_dim.w,
chunk_dim);
dnnType alpha = dnnType(1);
dnnType beta = dnnType(0);
if(!batchnorm) {
// bias
alpha = dnnType(1);
beta = dnnType(1);
checkCUDNN( cudnnAddTensor(net->cudnnHandle,
&alpha, biasTensorDesc, bias_d,
&beta, dstTensorDesc, dstData) );
} else {
alpha = dnnType(1);
beta = dnnType(0);
checkCUDNN( cudnnBatchNormalizationForwardInference(net->cudnnHandle,
CUDNN_BATCHNORM_SPATIAL, &alpha, &beta,
dstTensorDesc, dstData, dstTensorDesc,
dstData, biasTensorDesc, //same tensor descriptor as bias
scales_d, bias_d, mean_d, variance_d,
TKDNN_BN_MIN_EPSILON) );
}
//update data dimensions
dim = output_dim;
return dstData;
}
}}
+8 -9
View File
@@ -2,11 +2,10 @@
#include "Layer.h"
namespace tkDNN {
namespace tk { namespace dnn {
Dense::Dense(Network *net, dataDim_t in_dim,
int out_ch, const char* fname_weights, const char* fname_bias) :
LayerWgs(net, in_dim, in_dim.tot(), out_ch, 1, 1, 1, fname_weights, fname_bias) {
Dense::Dense(Network *net, int out_ch, std::string fname_weights) :
LayerWgs(net, net->getOutputDim().tot(), out_ch, 1, 1, 1, fname_weights) {
output_dim.n = 1;
output_dim.c = out_ch;
@@ -15,7 +14,7 @@ Dense::Dense(Network *net, dataDim_t in_dim,
output_dim.l = 1;
//allocate data for infer result
checkCuda( cudaMalloc(&dstData, output_dim.tot()*sizeof(value_type)) );
checkCuda( cudaMalloc(&dstData, output_dim.tot()*sizeof(dnnType)) );
}
Dense::~Dense() {
@@ -23,7 +22,7 @@ Dense::~Dense() {
checkCuda( cudaFree(dstData) );
}
value_type* Dense::infer(dataDim_t &dim, value_type* srcData) {
dnnType* Dense::infer(dataDim_t &dim, dnnType* srcData) {
if (dim.n != 1)
FatalError("Not Implemented");
@@ -34,9 +33,9 @@ value_type* Dense::infer(dataDim_t &dim, value_type* srcData) {
if (dim_x != input_dim.tot())
FatalError("Input mismatch");
value_type alpha = value_type(1), beta = value_type(1);
dnnType alpha = dnnType(1), beta = dnnType(1);
// place bias into dstData
checkCuda( cudaMemcpy(dstData, bias_d, dim_y*sizeof(value_type), cudaMemcpyDeviceToDevice) );
checkCuda( cudaMemcpy(dstData, bias_d, dim_y*sizeof(dnnType), cudaMemcpyDeviceToDevice) );
//do matrix moltiplication
checkERROR( cublasSgemv(net->cublasHandle, CUBLAS_OP_T,
@@ -56,4 +55,4 @@ value_type* Dense::infer(dataDim_t &dim, value_type* srcData) {
return dstData;
}
}
}}
+5 -6
View File
@@ -3,12 +3,11 @@
#include "Layer.h"
#include "kernels.h"
namespace tkDNN {
namespace tk { namespace dnn {
Flatten::Flatten(Network *net, dataDim_t input_dim) :
Layer(net, input_dim) {
Flatten::Flatten(Network *net) : Layer(net) {
checkCuda( cudaMalloc(&dstData, input_dim.tot()*sizeof(value_type)) );
checkCuda( cudaMalloc(&dstData, input_dim.tot()*sizeof(dnnType)) );
output_dim.n = 1;
output_dim.c = input_dim.tot();
@@ -23,7 +22,7 @@ Flatten::~Flatten() {
checkCuda( cudaFree(dstData) );
}
value_type* Flatten::infer(dataDim_t &dim, value_type* srcData) {
dnnType* Flatten::infer(dataDim_t &dim, dnnType* srcData) {
//transpose per channel
matrixTranspose(net->cublasHandle, srcData, dstData, dim.c, dim.h*dim.w*dim.l);
@@ -34,4 +33,4 @@ value_type* Flatten::infer(dataDim_t &dim, value_type* srcData) {
return dstData;
}
}
}}
+165
View File
@@ -0,0 +1,165 @@
#include "Int8BatchStream.h"
#include <opencv2/core/core.hpp>
#include <opencv2/dnn/dnn.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
BatchStream::BatchStream(tk::dnn::dataDim_t dim, int batchSize, int maxBatches, const std::string& fileimglist, const std::string& filelabellist) {
mBatchSize = batchSize;
mMaxBatches = maxBatches;
mDims = nvinfer1::DimsNCHW{ dim.n, dim.c, dim.h, dim.w };
mHeight = dim.h;
mWidth = dim.w;
mImageSize = mDims.c()*mDims.h()*mDims.w();
mBatch.resize(mBatchSize*mImageSize, 0);
mLabels.resize(mBatchSize, 0);
mFileBatch.resize(mDims.n()*mImageSize, 0);
mFileLabels.resize(mDims.n(), 0);
mFileImgList = fileimglist;
readInListFile(fileimglist, mListImg);
mFileLabelList = filelabellist;
readInListFile(filelabellist, mListLabel);
reset(0);
}
void BatchStream::reset(int firstBatch) {
mBatchCount = 0;
mFileCount = 0;
mFileBatchPos = mDims.n();
skip(firstBatch);
}
bool BatchStream::next() {
std::cout<<"Next batch: "<<mBatchCount<<" of "<<mMaxBatches<<"\n";
if (mBatchCount == mMaxBatches-1)
return false;
for (int csize = 1, batchPos = 0; batchPos < mBatchSize; batchPos += csize, mFileBatchPos += csize) {
assert(mFileBatchPos > 0 && mFileBatchPos <= mDims.n());
if (mFileBatchPos == mDims.n() && !update())
return false;
csize = std::min(mBatchSize - batchPos, mDims.n() - mFileBatchPos);
std::copy_n(getFileBatch() + mFileBatchPos * mImageSize, csize * mImageSize, getBatch() + batchPos * mImageSize);
std::copy_n(getFileLabels() + mFileBatchPos, csize, getLabels() + batchPos);
}
mBatchCount++;
return true;
}
void BatchStream::skip(int skipCount) {
if (mBatchSize >= mDims.n() && mBatchSize%mDims.n() == 0 && mFileBatchPos == mDims.n()) {
mFileCount += skipCount * mBatchSize / mDims.n();
return;
}
int x = mBatchCount;
for (int i = 0; i < skipCount; i++)
next();
mBatchCount = x;
}
void BatchStream::readInListFile(const std::string& dataFilePath, std::vector<std::string>& mListIn) {
// dataFilePath contains the list of image paths
int count = 0;
FILE* f = fopen(dataFilePath.c_str(), "r");
if (!f)
FatalError("failed to open " + dataFilePath);
char str[512];
while (fgets(str, 512, f) != NULL) {
for (int i = 0; str[i] != '\0'; ++i) {
if (str[i] == '\n'){
str[i] = '\0';
break;
}
}
count ++;
mListIn.push_back(str);
if(count == mMaxBatches)
break;
}
fclose(f);
}
void BatchStream::readCVimage(std::string inputFileName, std::vector<float>& res, bool fixshape) {
// unaltered original DsImage
cv::Mat m_OrigImage;
// letterboxed DsImage given to the network as input
cv::Mat m_LetterboxImage;
m_OrigImage = cv::imread(inputFileName, cv::IMREAD_COLOR);
if (!m_OrigImage.data || m_OrigImage.cols <= 0 || m_OrigImage.rows <= 0)
FatalError("Unable to open " + inputFileName);
int m_Height = m_OrigImage.rows;
int m_Width = m_OrigImage.cols;
if(fixshape) {
m_Height = mHeight;
m_Width = mWidth;
}
std::cout<<"image is "<<inputFileName<<": "<<m_Height<<" * "<<m_Width<<std::endl;
// resize the DsImage with scale
float dim = std::max(m_Height, m_Width);
int resizeH = ((m_Height / dim) * m_Height);
int resizeW = ((m_Width / dim) * m_Width);
float m_ScalingFactor = static_cast<float>(resizeH) / static_cast<float>(m_Height);
// Additional checks for images with non even dims
if ((m_Width - resizeW) % 2) resizeW--;
if ((m_Height - resizeH) % 2) resizeH--;
assert((m_Width - resizeW) % 2 == 0);
assert((m_Height - resizeH) % 2 == 0);
int m_XOffset = (m_Width - resizeW) / 2;
int m_YOffset = (m_Height - resizeH) / 2;
assert(2 * m_XOffset + resizeW == m_Width);
assert(2 * m_YOffset + resizeH == m_Height);
// resizing
cv::resize(m_OrigImage, m_LetterboxImage, cv::Size(resizeW, resizeH), 0, 0, cv::INTER_CUBIC);
// letterboxing
cv::copyMakeBorder(m_LetterboxImage, m_LetterboxImage, m_YOffset, m_YOffset, m_XOffset,
m_XOffset, cv::BORDER_CONSTANT, cv::Scalar(128, 128, 128));
m_LetterboxImage.convertTo(m_LetterboxImage, CV_32FC3, 1 / 255.0);
// converting to RGB and NCHW format
m_LetterboxImage = cv::dnn::blobFromImage(m_LetterboxImage);
res.assign(m_LetterboxImage.begin<float>(), m_LetterboxImage.end<float>());
}
void BatchStream::readLabels(std::string inputFileName, std::vector<float>& ris) {
std::ifstream is(inputFileName.c_str());
std::string line;
while (std::getline(is, line))
{
std::istringstream iss(line);
float val;
if(!(iss >> val)) { break; } // error
ris.push_back(val);
}
}
bool BatchStream::update() {
std::string imgFileName = mListImg[mFileCount];
std::string labelFileName = mListLabel[mFileCount];
mFileCount++;
//read image
mFileBatch.clear();
readCVimage(imgFileName, mFileBatch);
// std::transform(
// singleImg_rawData.begin(), singleImg_rawData.end(), mFileBatch.begin(), [](uint8_t val) { return static_cast<float>(val); });
//read label
mFileLabels.clear();
readLabels(labelFileName, mFileLabels);
// std::transform(
// singleLabels_rawData.begin(), singleLabels_rawData.end(), mFileLabels.begin(), [](uint8_t val) { return static_cast<float>(val); });
mFileBatchPos = 0;
return true;
}
+46
View File
@@ -0,0 +1,46 @@
#include "Int8Calibrator.h"
Int8EntropyCalibrator::Int8EntropyCalibrator(BatchStream& stream, int firstBatch,
const std::string& calibTableFilePath,
const std::string& inputBlobName,
bool readCache):
mStream(stream),
mCalibTableFilePath(calibTableFilePath),
mInputBlobName(inputBlobName.c_str()),
mReadCache(readCache) {
nvinfer1::DimsNCHW dims = mStream.getDims();
mInputCount = mStream.getBatchSize() * dims.c() * dims.h() * dims.w();
checkCuda(cudaMalloc(&mDeviceInput, mInputCount * sizeof(float)));
mStream.reset(firstBatch);
}
bool Int8EntropyCalibrator::getBatch(void* bindings[], const char* names[], int nbBindings) {
if (!mStream.next())
return false;
checkCuda(cudaMemcpy(mDeviceInput, mStream.getBatch(), mInputCount * sizeof(float), cudaMemcpyHostToDevice));
assert(!strcmp(names[0], mInputBlobName.c_str()));
bindings[0] = mDeviceInput;
return true;
}
const void* Int8EntropyCalibrator::readCalibrationCache(size_t& length) {
mCalibrationCache.clear();
assert(!mCalibTableFilePath.empty());
std::ifstream input(mCalibTableFilePath, std::ios::binary);
input >> std::noskipws;
input >> std::noskipws;
if (mReadCache && input.good())
std::copy(std::istream_iterator<char>(input), std::istream_iterator<char>(),
std::back_inserter(mCalibrationCache));
length = mCalibrationCache.size();
return length ? &mCalibrationCache[0] : nullptr;
}
void Int8EntropyCalibrator::writeCalibrationCache(const void* cache, size_t length) {
assert(!mCalibTableFilePath.empty());
std::ofstream output(mCalibTableFilePath, std::ios::binary);
output.write(reinterpret_cast<const char*>(cache), length);
output.close();
}
+331
View File
@@ -0,0 +1,331 @@
#include <iostream>
#include "Layer.h"
namespace tk { namespace dnn {
LSTM::LSTM( Network *net, int hiddensize, bool returnSeq, std::string fname_weights) :
Layer(net) {
this->returnSeq = returnSeq;
int batchSize = input_dim.n;
int inputSize = input_dim.c;
seqLen = input_dim.w;
stateSize = hiddensize;
// init Tensor Descriptors
std::vector<cudnnTensorDescriptor_t> x_vec(seqLen);
std::vector<cudnnTensorDescriptor_t> y_vec(seqLen);
int dimA[3];
int strideA[3];
for (int i = 0; i < seqLen; i++) {
checkCUDNN(cudnnCreateTensorDescriptor(&x_vec[i]));
checkCUDNN(cudnnCreateTensorDescriptor(&y_vec[i]));
dimA[0] = batchSize;
dimA[1] = inputSize;
dimA[2] = 1;
dimA[0] = batchSize;
dimA[1] = inputSize;
strideA[0] = dimA[2] * dimA[1];
strideA[1] = dimA[2];
strideA[2] = 1;
checkCUDNN(cudnnSetTensorNdDescriptor(x_vec[i],
net->dataType, 3, dimA, strideA));
dimA[0] = batchSize;
dimA[1] = stateSize;
dimA[2] = 1;
strideA[0] = dimA[2] * dimA[1];
strideA[1] = dimA[2];
strideA[2] = 1;
checkCUDNN(cudnnSetTensorNdDescriptor(y_vec[i],
net->dataType, 3, dimA, strideA));
}
// apply tensordesc
x_desc_vec_ = x_vec;
y_desc_vec_ = y_vec;
// set the state tensors
dimA[0] = numLayers;
dimA[1] = batchSize;
dimA[2] = stateSize;
strideA[0] = dimA[2] * dimA[1];
strideA[1] = dimA[2];
strideA[2] = 1;
checkCUDNN(cudnnCreateTensorDescriptor(&hx_desc_));
checkCUDNN(cudnnCreateTensorDescriptor(&cx_desc_));
checkCUDNN(cudnnCreateTensorDescriptor(&hy_desc_));
checkCUDNN(cudnnCreateTensorDescriptor(&cy_desc_));
checkCUDNN(cudnnSetTensorNdDescriptor(hx_desc_, net->dataType, 3, dimA, strideA));
checkCUDNN(cudnnSetTensorNdDescriptor(cx_desc_, net->dataType, 3, dimA, strideA));
checkCUDNN(cudnnSetTensorNdDescriptor(hy_desc_, net->dataType, 3, dimA, strideA));
checkCUDNN(cudnnSetTensorNdDescriptor(cy_desc_, net->dataType, 3, dimA, strideA));
// allocate dnnType *hx_ptr, *cx_ptr, *hy_ptr, *cy_ptr;
stateDataDim = dimA[0]*dimA[1]*dimA[2];
checkCuda( cudaMalloc(&hx_ptr, stateDataDim*sizeof(dnnType)) );
checkCuda( cudaMalloc(&cx_ptr, stateDataDim*sizeof(dnnType)) );
checkCuda( cudaMalloc(&hy_ptr, stateDataDim*sizeof(dnnType)) );
checkCuda( cudaMalloc(&cy_ptr, stateDataDim*sizeof(dnnType)) );
// Create Dropout descriptors // TODO: ??? IS IT NECESSARY ???
float dropoutprob = 0.1f; // random val ????
checkCUDNN(cudnnCreateDropoutDescriptor(&dropoutDesc));
checkCUDNN(cudnnDropoutGetStatesSize(net->cudnnHandle, &dropout_byte_));
dropout_size_ = dropout_byte_ / sizeof(dnnType);
checkCuda( cudaMalloc(&dropout_states_, dropout_byte_) );
uint64_t seed_ = 17 + rand() % 4096; // NOLINT(runtime/threadsafe_fn)
checkCUDNN(cudnnSetDropoutDescriptor(dropoutDesc,
net->cudnnHandle, dropoutprob, dropout_states_, dropout_byte_, seed_));
// RNN descriptors
checkCUDNN(cudnnCreateRNNDescriptor(&rnnDesc));
#if CUDNN_MAJOR > 7
checkCUDNN(cudnnSetRNNDescriptor_v6(net->cudnnHandle,
#else
checkCUDNN(cudnnSetRNNDescriptor(net->cudnnHandle,
#endif
rnnDesc, stateSize, numLayers, dropoutDesc,
cudnnRNNInputMode_t::CUDNN_LINEAR_INPUT,
//(bidirectional ? cudnnDirectionMode_t::CUDNN_BIDIRECTIONAL : cudnnDirectionMode_t::CUDNN_UNIDIRECTIONAL),
cudnnDirectionMode_t::CUDNN_UNIDIRECTIONAL,
cudnnRNNMode_t::CUDNN_LSTM,
cudnnRNNAlgo_t::CUDNN_RNN_ALGO_STANDARD,
net->dataType));
// Get temp space sizes
checkCUDNN(cudnnGetRNNWorkspaceSize(net->cudnnHandle,
rnnDesc, seqLen, x_desc_vec_.data(), &workspace_byte_));
workspace_size_ = workspace_byte_ / sizeof(dnnType);
checkCuda( cudaMalloc(&work_space_, workspace_byte_) );
// Check that number of params are correct
size_t cudnn_param_size;
checkCUDNN(cudnnGetRNNParamsSize(net->cudnnHandle,
rnnDesc,x_desc_vec_[0], &cudnn_param_size, net->dataType));
int cudnn_params = cudnn_param_size/sizeof(dnnType);
//std::cout<<"LSTM params size: "<<cudnn_params << ", bytes: "<<cudnn_param_size<<"\n";
// Set param descriptors
checkCUDNN(cudnnCreateFilterDescriptor(&w_desc_));
int dim_w[3] = {1, 1, 1};
dim_w[0] = cudnn_params;
checkCUDNN(cudnnSetFilterNdDescriptor(w_desc_,
net->dataType, net->tensorFormat, 3, dim_w));
// load params
std::cout<<"Reading weights: PARAMS="<<cudnn_params*2<<"\n";
readBinaryFile(fname_weights, cudnn_params*2, &w_h, &w_ptr);
// set forward and backward params
wf_ptr = w_ptr;
wb_ptr = w_ptr + cudnn_params;
//std::cout<<"wf: "<<wf_ptr<<" wb "<<wb_ptr<<"\n";
// set output dim
output_dim = input_dim;
output_dim.c = stateSize*(bidirectional ? 2 : 1);
// if retunseq is disabled only the last timestep is returned
if(!returnSeq) {
output_dim.h = 1;
output_dim.w = 1;
}
//allocate data for infer result
checkCuda( cudaMalloc(&dstData, output_dim.tot()*sizeof(dnnType)) );
// used during inference
one_output_dim = input_dim;
one_output_dim.c = stateSize;
checkCuda( cudaMalloc(&srcF, input_dim.tot()*sizeof(dnnType)) );
checkCuda( cudaMalloc(&srcB, input_dim.tot()*sizeof(dnnType)) );
checkCuda( cudaMalloc(&dstF, one_output_dim.tot()*sizeof(dnnType)) );
checkCuda( cudaMalloc(&dstB_NR, one_output_dim.tot()*sizeof(dnnType)) );
checkCuda( cudaMalloc(&dstB, one_output_dim.tot()*sizeof(dnnType)) );
/*
// Query weight layout
cudnnFilterDescriptor_t m_desc;
checkCUDNN(cudnnCreateFilterDescriptor(&m_desc));
dnnType *p;
int n = 8; // lstm layers
printCenteredTitle("WEIGHTS", '=', 20);
for (int i = 0; i < numLayers; ++i) {
for (int j = 0; j < n; ++j) {
checkCUDNN(cudnnGetRNNLinLayerMatrixParams(net->cudnnHandle, rnnDesc,
i, x_desc_vec_[0], w_desc_, 0, j, m_desc, (void**)&p));
std::cout << "ptr: " << ((int64_t)(p - NULL))/sizeof(dnnType)<<"\n";
cudnnDataType_t t;
cudnnTensorFormat_t f;
int ndim = 5;
int dims[5] = {0, 0, 0, 0, 0};
checkCUDNN(cudnnGetFilterNdDescriptor(m_desc, ndim, &t, &f, &ndim, &dims[0]));
std::cout << "(layer, linlayer): " << i << " " << j << "\n";
int tot = 1;
for (int i = 0; i < ndim; ++i) {
std::cout << dims[i] << " ";
tot *= dims[i];
}
std::cout<<"\t-> "<<tot<<"\n\n";
}
}
printCenteredTitle("BIAS", '=', 20);
for (int i = 0; i < numLayers; ++i) {
for (int j = 0; j < n; ++j) {
checkCUDNN(cudnnGetRNNLinLayerBiasParams(net->cudnnHandle, rnnDesc,
i, x_desc_vec_[0], w_desc_, 0, j, m_desc, (void**)&p));
std::cout << "ptr: " << ((int64_t)(p - NULL))/sizeof(dnnType)<<"\n";
cudnnDataType_t t;
cudnnTensorFormat_t f;
int ndim = 5;
int dims[5] = {0, 0, 0, 0, 0};
checkCUDNN(cudnnGetFilterNdDescriptor(m_desc, ndim, &t, &f, &ndim, &dims[0]));
std::cout << "(layer, linlayer): " << i << " " << j << "\n";
int tot = 1;
for (int i = 0; i < ndim; ++i) {
std::cout << dims[i] << " ";
tot *= dims[i];
}
std::cout<<"\t-> "<<tot<<"\n\n";
}
}
checkCUDNN(cudnnDestroyFilterDescriptor(m_desc));
*/
}
LSTM::~LSTM() {
checkCuda(cudaFree(hx_ptr));
checkCuda(cudaFree(cx_ptr));
checkCuda(cudaFree(hy_ptr));
checkCuda(cudaFree(cy_ptr));
checkCuda(cudaFree(w_ptr ));
checkCuda(cudaFree(work_space_ ));
checkCuda(cudaFree(dropout_states_));
checkCuda(cudaFree(srcF));
checkCuda(cudaFree(srcB));
checkCuda(cudaFree(dstF));
checkCuda(cudaFree(dstB_NR));
checkCuda(cudaFree(dstB));
checkCuda(cudaFree(dstData));
}
dnnType* LSTM::infer(dataDim_t &dim, dnnType* srcData) {
// transpose input
matrixTranspose(net->cublasHandle, srcData, srcF, dim.c, dim.h*dim.w*dim.l);
// build srcB as reversed srcF
for(int i=0; i<input_dim.w; i++) {
int off_0 = i*(input_dim.c);
int off_1 = (i+1)*(input_dim.c);
checkCuda( cudaMemcpy(srcB + dim.tot() - off_1, srcF + off_0,
input_dim.c*sizeof(dnnType), cudaMemcpyDeviceToDevice));
}
// forward
{
// reset states
checkCuda( cudaMemset(hx_ptr, 0, stateDataDim*sizeof(float)) );
checkCuda( cudaMemset(cx_ptr, 0, stateDataDim*sizeof(float)) );
checkCUDNN(cudnnRNNForwardInference(net->cudnnHandle,
rnnDesc,
seqLen, // number of time steps (nT)
x_desc_vec_.data(), // input array of desc (nT*nC_in)
srcF, // input pointer
hx_desc_, // initial hidden state desc
hx_ptr, // initial hidden state pointer
cx_desc_, // initial cell state desc
cx_ptr, // initial cell state pointer
w_desc_, // weights desc
wf_ptr, // weights pointer
y_desc_vec_.data(), // output desc (nT*nC_out)
dstF, // output pointer
hy_desc_, // final hidden state desc
hy_ptr, // final hidden state pointer
cy_desc_, // final cell state desc
cy_ptr, // final cell state pointer
work_space_, // workspace pointer
workspace_byte_)); // workspace size
}
// backward
{
// reset states
checkCuda( cudaMemset(hx_ptr, 0, stateDataDim*sizeof(float)) );
checkCuda( cudaMemset(cx_ptr, 0, stateDataDim*sizeof(float)) );
checkCUDNN(cudnnRNNForwardInference(net->cudnnHandle,
rnnDesc,
seqLen, // number of time steps (nT)
x_desc_vec_.data(), // input array of desc (nT*nC_in)
srcB, // input pointer
hx_desc_, // initial hidden state desc
hx_ptr, // initial hidden state pointer
cx_desc_, // initial cell state desc
cx_ptr, // initial cell state pointer
w_desc_, // weights desc
wb_ptr, // weights pointer
y_desc_vec_.data(), // output desc (nT*nC_out)
dstB_NR, // output pointer
hy_desc_, // final hidden state desc
hy_ptr, // final hidden state pointer
cy_desc_, // final cell state desc
cy_ptr, // final cell state pointer
work_space_, // workspace pointer
workspace_byte_)); // workspace size
}
// reverse order of dstB
for(int i=0; i<one_output_dim.w; i++) {
int off_0 = i*(one_output_dim.c);
int off_1 = (i+1)*(one_output_dim.c);
checkCuda( cudaMemcpy(dstB + one_output_dim.tot() - off_1, dstB_NR + off_0,
one_output_dim.c*sizeof(dnnType), cudaMemcpyDeviceToDevice));
}
// if retunseq is disabled only the last timestep is returned
if(returnSeq) {
// forward transpose
matrixTranspose(net->cublasHandle, dstF, dstData,
one_output_dim.h* one_output_dim.w*one_output_dim.l, one_output_dim.c);
// backward transpose
matrixTranspose(net->cublasHandle, dstB, dstData + one_output_dim.tot(),
one_output_dim.h* one_output_dim.w*one_output_dim.l, one_output_dim.c);
} else {
// copy last of forward
checkCuda( cudaMemcpy(dstData, dstF + one_output_dim.tot() - one_output_dim.c,
one_output_dim.c*sizeof(dnnType), cudaMemcpyDeviceToDevice));
// copy first of backward
checkCuda( cudaMemcpy(dstData + one_output_dim.c, dstB,
one_output_dim.c*sizeof(dnnType), cudaMemcpyDeviceToDevice));
}
dim = output_dim;
return dstData;
}
}}
+18 -10
View File
@@ -2,25 +2,33 @@
#include "Layer.h"
namespace tkDNN {
namespace tk { namespace dnn {
Layer::Layer(Network *net, dataDim_t in_dim) {
Layer::Layer(Network *net) {
this->net = net;
this->input_dim = in_dim;
this->output_dim = in_dim;
checkCUDNN( cudnnCreateTensorDescriptor(&srcTensorDesc) );
checkCUDNN( cudnnCreateTensorDescriptor(&dstTensorDesc) );
this->final = false;
if(net != nullptr) {
this->input_dim = net->getOutputDim();
this->output_dim = input_dim;
checkCUDNN( cudnnCreateTensorDescriptor(&srcTensorDesc) );
checkCUDNN( cudnnCreateTensorDescriptor(&dstTensorDesc) );
if(!net->addLayer(this))
FatalError("Net reached max number of layers");
if(!net->addLayer(this))
FatalError("Net reached max number of layers");
}
}
Layer::~Layer() {
checkCUDNN( cudnnDestroyTensorDescriptor(srcTensorDesc) );
checkCUDNN( cudnnDestroyTensorDescriptor(dstTensorDesc) );
if(dstData != nullptr) {
cudaFree(dstData);
dstData = nullptr;
}
}
}
}}
+106 -14
View File
@@ -1,29 +1,121 @@
#include <iostream>
#include <string.h>
#include "Layer.h"
#include "kernels.h"
namespace tkDNN {
LayerWgs::LayerWgs(Network *net, dataDim_t in_dim,
int inputs, int outputs, int kh, int kw, int kl,
const char* fname_weights, const char* fname_bias) : Layer(net, in_dim) {
namespace tk { namespace dnn {
LayerWgs::LayerWgs(Network *net, int inputs, int outputs,
int kh, int kw, int kl,
std::string fname_weights, bool batchnorm, bool additional_bias, bool deConv, int groups) : Layer(net) {
inputs = inputs/groups;
this->inputs = inputs;
this->outputs = outputs;
this->weights_path = std::string(fname_weights);
this->bias_path = std::string(fname_bias);
std::cout<<"Reading weights: I="<<inputs<<" O="<<outputs<<" KERNEL="<<kh<<"x"<<kw<<"x"<<kl<<"\n";
readBinaryFile(weights_path.c_str(), inputs*outputs*kh*kw*kl, &data_h, &data_d);
readBinaryFile(bias_path.c_str(), outputs, &bias_h, &bias_d);
int seek = 0;
readBinaryFile(weights_path.c_str(), inputs*outputs*kh*kw*kl, &data_h, &data_d, seek);
seek += inputs*outputs*kh*kw*kl;
this->additional_bias = additional_bias;
if(additional_bias) {
readBinaryFile(weights_path.c_str(), outputs, &bias2_h, &bias2_d, seek);
seek += outputs;
}
readBinaryFile(weights_path.c_str(), outputs, &bias_h, &bias_d, seek);
this->batchnorm = batchnorm;
if(batchnorm) {
seek += outputs;
readBinaryFile(weights_path.c_str(), outputs, &scales_h, &scales_d, seek);
seek += outputs;
readBinaryFile(weights_path.c_str(), outputs, &mean_h, &mean_d, seek);
seek += outputs;
readBinaryFile(weights_path.c_str(), outputs, &variance_h, &variance_d, seek);
float eps = TKDNN_BN_MIN_EPSILON;
power_h = new dnnType[outputs];
for(int i=0; i<outputs; i++) power_h[i] = 1.0f;
for(int i=0; i<outputs; i++)
mean_h[i] = mean_h[i] / -sqrt(eps + variance_h[i]);
for(int i=0; i<outputs; i++)
variance_h[i] = 1.0f / sqrt(eps + variance_h[i]);
}
if(!net->fp16)
return;
//convert to fp16
int w_size = inputs*outputs*kh*kw*kl;
data16_h = new __half[w_size];
cudaMalloc(&data16_d, w_size*sizeof(__half));
float2half(data_d, data16_d, w_size);
cudaMemcpy(data16_h, data16_d, w_size*sizeof(__half), cudaMemcpyDeviceToHost);
if(additional_bias){
int b2_size = outputs;
bias216_h = new __half[b2_size];
cudaMalloc(&bias216_d, w_size*sizeof(__half));
float2half(bias2_d, bias216_d, b2_size);
cudaMemcpy(bias216_h, bias216_d, b2_size*sizeof(__half), cudaMemcpyDeviceToHost);
}
int b_size = outputs;
bias16_h = new __half[b_size];
cudaMalloc(&bias16_d, w_size*sizeof(__half));
float2half(bias_d, bias16_d, b_size);
cudaMemcpy(bias16_h, bias16_d, b_size*sizeof(__half), cudaMemcpyDeviceToHost);
if(batchnorm) {
power16_h = new __half[b_size];
mean16_h = new __half[b_size];
variance16_h = new __half[b_size];
scales16_h = new __half[b_size];
cudaMalloc(&power16_d, b_size*sizeof(__half));
cudaMalloc(&mean16_d, b_size*sizeof(__half));
cudaMalloc(&variance16_d, b_size*sizeof(__half));
cudaMalloc(&scales16_d, b_size*sizeof(__half));
//temporary buffers
float *tmp_d;
cudaMalloc(&tmp_d, b_size*sizeof(float));
//init power array of ones
cudaMemcpy(tmp_d, power_h, b_size*sizeof(float), cudaMemcpyHostToDevice);
float2half(tmp_d, power16_d, b_size);
cudaMemcpy(power16_h, power16_d, b_size*sizeof(__half), cudaMemcpyDeviceToHost);
//mean array
cudaMemcpy(tmp_d, mean_h, b_size*sizeof(float), cudaMemcpyHostToDevice);
float2half(tmp_d, mean16_d, b_size);
cudaMemcpy(mean16_h, mean16_d, b_size*sizeof(__half), cudaMemcpyDeviceToHost);
//convert variance
cudaMemcpy(tmp_d, variance_h, b_size*sizeof(float), cudaMemcpyHostToDevice);
float2half(tmp_d, variance16_d, b_size);
cudaMemcpy(variance16_h, variance16_d, b_size*sizeof(__half), cudaMemcpyDeviceToHost);
//conver scales
float2half(scales_d, scales16_d, b_size);
cudaMemcpy(scales16_h, scales16_d, b_size*sizeof(__half), cudaMemcpyDeviceToHost);
cudaFree(tmp_d);
}
}
LayerWgs::~LayerWgs() {
delete [] data_h;
delete [] bias_h;
checkCuda( cudaFree(data_d) );
checkCuda( cudaFree(bias_d) );
releaseHost();
releaseDevice();
}
}
}}
+311
View File
@@ -0,0 +1,311 @@
#include "MobilenetDetection.h"
bool boxProbCmp(const tk::dnn::box &a, const tk::dnn::box &b){
return (a.prob > b.prob);
}
namespace tk{ namespace dnn{
void MobilenetDetection::generate_ssd_priors(const SSDSpec *specs, const int n_specs, bool clamp){
nPriors = 0;
for (int i = 0; i < n_specs; i++){
nPriors += specs[i].featureSize * specs[i].featureSize * 6;
}
priors = (float *)malloc(N_COORDS * nPriors * sizeof(float));
int i_prio = 0;
float scale, x_center, y_center, h, w, size, ratio;
int min, max;
for (int i = 0; i < n_specs; i++){
scale = (float)imageSize / (float)specs[i].shrinkage;
min = specs[i].boxHeight > specs[i].boxWidth ? specs[i].boxWidth : specs[i].boxHeight;
max = specs[i].boxHeight < specs[i].boxWidth ? specs[i].boxWidth : specs[i].boxHeight;
for (int j = 0; j < specs[i].featureSize; j++){
for (int k = 0; k < specs[i].featureSize; k++){
//small sized square box
size = min;
x_center = (k + 0.5f) / scale;
y_center = (j + 0.5f) / scale;
h = w = (float)size / (float)imageSize;
priors[i_prio * N_COORDS + 0] = x_center;
priors[i_prio * N_COORDS + 1] = y_center;
priors[i_prio * N_COORDS + 2] = w;
priors[i_prio * N_COORDS + 3] = h;
++i_prio;
//big sized square box
size = sqrt(max * min);
h = w = (float)size / (float)imageSize;
priors[i_prio * N_COORDS + 0] = x_center;
priors[i_prio * N_COORDS + 1] = y_center;
priors[i_prio * N_COORDS + 2] = w;
priors[i_prio * N_COORDS + 3] = h;
++i_prio;
//change h/w ratio of the small sized box
size = min;
h = w = size / (float)imageSize;
ratio = sqrt(specs[i].ratio1);
priors[i_prio * N_COORDS + 0] = x_center;
priors[i_prio * N_COORDS + 1] = y_center;
priors[i_prio * N_COORDS + 2] = w * ratio;
priors[i_prio * N_COORDS + 3] = h / ratio;
++i_prio;
priors[i_prio * N_COORDS + 0] = x_center;
priors[i_prio * N_COORDS + 1] = y_center;
priors[i_prio * N_COORDS + 2] = w / ratio;
priors[i_prio * N_COORDS + 3] = h * ratio;
++i_prio;
ratio = sqrt(specs[i].ratio2);
priors[i_prio * N_COORDS + 0] = x_center;
priors[i_prio * N_COORDS + 1] = y_center;
priors[i_prio * N_COORDS + 2] = w * ratio;
priors[i_prio * N_COORDS + 3] = h / ratio;
++i_prio;
priors[i_prio * N_COORDS + 0] = x_center;
priors[i_prio * N_COORDS + 1] = y_center;
priors[i_prio * N_COORDS + 2] = w / ratio;
priors[i_prio * N_COORDS + 3] = h * ratio;
++i_prio;
}
}
}
if (clamp){
for (int i = 0; i < nPriors * N_COORDS; i++){
priors[i] = priors[i] > 1.0f ? 1.0f : priors[i];
priors[i] = priors[i] < 0.0f ? 0.0f : priors[i];
}
}
}
void MobilenetDetection::convert_locatios_to_boxes_and_center(){
float cur_x, cur_y;
for (int i = 0; i < nPriors; i++){
locations_h[i * N_COORDS + 0] = locations_h[i * N_COORDS + 0] * centerVariance * priors[i * N_COORDS + 2] + priors[i * N_COORDS + 0];
locations_h[i * N_COORDS + 1] = locations_h[i * N_COORDS + 1] * centerVariance * priors[i * N_COORDS + 3] + priors[i * N_COORDS + 1];
locations_h[i * N_COORDS + 2] = exp(locations_h[i * N_COORDS + 2] * sizeVariance) * priors[i * N_COORDS + 2];
locations_h[i * N_COORDS + 3] = exp(locations_h[i * N_COORDS + 3] * sizeVariance) * priors[i * N_COORDS + 3];
cur_x = locations_h[i * N_COORDS + 0];
cur_y = locations_h[i * N_COORDS + 1];
locations_h[i * N_COORDS + 0] = cur_x - locations_h[i * N_COORDS + 2] / 2;
locations_h[i * N_COORDS + 1] = cur_y - locations_h[i * N_COORDS + 3] / 2;
locations_h[i * N_COORDS + 2] = cur_x + locations_h[i * N_COORDS + 2] / 2;
locations_h[i * N_COORDS + 3] = cur_y + locations_h[i * N_COORDS + 3] / 2;
}
}
float MobilenetDetection::iou(const tk::dnn::box &a, const tk::dnn::box &b){
float max_x = a.x > b.x ? a.x : b.x;
float max_y = a.y > b.y ? a.y : b.y;
float min_w = a.w < b.w ? a.w : b.w;
float min_h = a.h < b.h ? a.h : b.h;
float ao_w = min_w - max_x > 0 ? min_w - max_x : 0;
float ao_h = min_h - max_y > 0 ? min_h - max_y : 0;
float area_overlap = ao_w * ao_h;
float area_0_w = a.w - a.x > 0 ? a.w - a.x : 0;
float area_0_h = a.h - a.y > 0 ? a.h - a.y : 0;
float area_1_w = b.w - b.x > 0 ? b.w - b.x : 0;
float area_1_h = b.h - b.y > 0 ? b.h - b.y : 0;
float area_0 = area_0_h * area_0_w;
float area_1 = area_1_h * area_1_w;
float iou = area_overlap / (area_0 + area_1 - area_overlap + 1e-5);
return iou;
}
bool MobilenetDetection::init(const std::string& tensor_path, const int n_classes, const int n_batches){
std::cout<<(tensor_path).c_str()<<"\n";
netRT = new tk::dnn::NetworkRT(NULL, (tensor_path).c_str());
imageSize = netRT->input_dim.h;
classes = n_classes;
nBatches = n_batches;
SSDSpec specs[N_SSDSPEC];
if(imageSize == 300){
specs[0].setAll(19, 16, 60, 105, 2, 3);
specs[1].setAll(10, 32, 105, 150, 2, 3);
specs[2].setAll(5, 64, 150, 195, 2, 3);
specs[3].setAll(3, 100, 195, 240, 2, 3);
specs[4].setAll(2, 150, 240, 285, 2, 3);
specs[5].setAll(1, 300, 285, 330, 2, 3);
}
else if(imageSize == 512){
specs[0].setAll(32, 16, 60, 105, 2, 3);
specs[1].setAll(16, 32, 105, 150, 2, 3);
specs[2].setAll(8, 64, 150, 195, 2, 3);
specs[3].setAll(4, 100, 195, 240, 2, 3);
specs[4].setAll(2, 150, 240, 285, 2, 3);
specs[5].setAll(1, 300, 285, 330, 2, 3);
}
else{
FatalError("Input size for mobilenet not supported");
}
generate_ssd_priors(specs, N_SSDSPEC);
#ifndef OPENCV_CUDACONTRIB
checkCuda(cudaMallocHost(&input, sizeof(dnnType) * netRT->input_dim.tot() * nBatches));
#endif
checkCuda(cudaMalloc(&input_d, sizeof(dnnType) * netRT->input_dim.tot() * nBatches));
locations_h = (float *)malloc(N_COORDS * nPriors * sizeof(float));
confidences_h = (float *)malloc(nPriors * classes * sizeof(float));
for (int c = 0; c < classes; c++){
int offset = c * 123457 % classes;
float r = getColor(2, offset, classes);
float g = getColor(1, offset, classes);
float b = getColor(0, offset, classes);
colors[c] = cv::Scalar(int(255.0 * b), int(255.0 * g), int(255.0 * r));
}
if(classes == 11){ //BDD
const char *classes_names_[] = {
"person","car","truck","bus","motor","bike","rider","traffic light","traffic sign","train"};
classesNames = std::vector<std::string>(classes_names_, std::end(classes_names_));
}
else if(classes == 21){ //VOC
const char *classes_names_[] = {
"aeroplane", "bicycle", "bird", "boat", "bottle", "bus",
"car", "cat", "chair", "cow", "diningtable", "dog", "horse", "motorbike",
"person", "pottedplant", "sheep", "sofa", "train", "tvmonitor"};
classesNames = std::vector<std::string>(classes_names_, std::end(classes_names_));
}
else if (classes == 81){ //COCO
const char *classes_names_[] = {
"person" , "bicycle" , "car" , "motorbike" , "aeroplane" , "bus" ,
"train" , "truck" , "boat" , "traffic light" , "fire hydrant" , "stop sign" ,
"parking meter" , "bench" , "bird" , "cat" , "dog" , "horse" , "sheep" , "cow" ,
"elephant" , "bear" , "zebra" , "giraffe" , "backpack" , "umbrella" , "handbag" ,
"tie" , "suitcase" , "frisbee" , "skis" , "snowboard" , "sports ball" , "kite" ,
"baseball bat" , "baseball glove" , "skateboard" , "surfboard" , "tennis racket" ,
"bottle" , "wine glass" , "cup" , "fork" , "knife" , "spoon" , "bowl" , "banana" ,
"apple" , "sandwich" , "orange" , "broccoli" , "carrot" , "hot dog" , "pizza" ,
"donut" , "cake" , "chair" , "sofa" , "pottedplant" , "bed" , "diningtable" ,
"toilet" , "tvmonitor" , "laptop" , "mouse" , "remote" , "keyboard" ,
"cell phone" , "microwave" , "oven" , "toaster" , "sink" , "refrigerator" ,
"book" , "clock" , "vase" , "scissors" , "teddy bear" , "hair drier" , "toothbrush"};
classesNames = std::vector<std::string>(classes_names_, std::end(classes_names_));
}
else{
FatalError("Number of classes not supported for mobilenet");
}
return 1;
}
void MobilenetDetection::preprocess(cv::Mat &frame, const int bi){
#ifdef OPENCV_CUDACONTRIB
//move original image on GPU
cv::cuda::GpuMat orig_img, frame_nomean;
orig_img = cv::cuda::GpuMat(frame);
//resize image, remove mean, divide by std
cv::cuda::resize (orig_img, orig_img, cv::Size(netRT->input_dim.w, netRT->input_dim.h));
orig_img.convertTo(frame_nomean, CV_32FC3, 1, -127);
frame_nomean.convertTo(imagePreproc, CV_32FC3, 1 / 128.0, 0);
//copy image into tensors
cv::cuda::split(imagePreproc, bgr);
for(int i=0; i < netRT->input_dim.c; i++){
int idx = i * imagePreproc.rows * imagePreproc.cols;
checkCuda( cudaMemcpy((void *)&input_d[idx + netRT->input_dim.tot()*bi], (void *)bgr[i].data, imagePreproc.rows * imagePreproc.cols* sizeof(float), cudaMemcpyDeviceToDevice) );
}
#else
//resize image, remove mean, divide by std
cv::Mat frame_nomean;
resize(frame, frame, cv::Size(netRT->input_dim.w, netRT->input_dim.h));
frame.convertTo(frame_nomean, CV_32FC3, 1, -127);
frame_nomean.convertTo(imagePreproc, CV_32FC3, 1 / 128.0, 0);
//copy image into tensor and copy it into GPU
cv::split(imagePreproc, bgr);
for (int i = 0; i < netRT->input_dim.c; i++){
int idx = i * imagePreproc.rows * imagePreproc.cols;
memcpy((void *)&input[idx + netRT->input_dim.tot()*bi], (void *)bgr[i].data, imagePreproc.rows * imagePreproc.cols * sizeof(dnnType));
}
checkCuda(cudaMemcpyAsync(input_d+ netRT->input_dim.tot()*bi, input + netRT->input_dim.tot()*bi, netRT->input_dim.tot() * sizeof(dnnType), cudaMemcpyHostToDevice, netRT->stream));
#endif
}
void MobilenetDetection::postprocess(const int bi, const bool mAP){
//get confidences and locations_h
dnnType *rt_out[2];
rt_out[0] = (dnnType *)netRT->buffersRT[3]+ netRT->buffersDIM[3].tot()*bi;
rt_out[1] = (dnnType *)netRT->buffersRT[4]+ netRT->buffersDIM[4].tot()*bi;
detected.clear();
checkCuda(cudaMemcpy(confidences_h, rt_out[0], nPriors * classes * sizeof(float), cudaMemcpyDeviceToHost));
checkCuda(cudaMemcpy(locations_h, rt_out[1], N_COORDS * nPriors * sizeof(float), cudaMemcpyDeviceToHost));
convert_locatios_to_boxes_and_center();
int width = originalSize[bi].width;
int height = originalSize[bi].height;
float *conf_per_class;
for (int i = 1; i < classes; i++){
conf_per_class = &confidences_h[i * nPriors];
std::vector<tk::dnn::box> boxes;
for (int j = 0; j < nPriors; j++){
if (conf_per_class[j] > confThreshold){
tk::dnn::box b;
b.cl = i;
b.prob = conf_per_class[j];
b.x = locations_h[j * N_COORDS + 0];
b.y = locations_h[j * N_COORDS + 1];
b.w = locations_h[j * N_COORDS + 2];
b.h = locations_h[j * N_COORDS + 3];
if(mAP)
for(int c=1; c<classes; c++)
b.probs.push_back(confidences_h[c * nPriors + j]);
boxes.push_back(b);
}
}
std::sort(boxes.begin(), boxes.end(), boxProbCmp);
std::vector<tk::dnn::box> remaining;
while (boxes.size() > 0){
remaining.clear();
tk::dnn::box b;
b.cl = boxes[0].cl -1 ; //remove background class
b.prob = boxes[0].prob;
b.x = boxes[0].x * width;
b.y = boxes[0].y * height;
b.w = boxes[0].w * width - b.x; //convert from x1 to width
b.h = boxes[0].h * height - b.y; //convert from y1 to height
detected.push_back(b);
for (size_t j = 1; j < boxes.size(); j++){
if (iou(boxes[0], boxes[j]) <= IoUThreshold){
remaining.push_back(boxes[j]);
}
}
boxes = remaining;
}
}
batchDetected.push_back(detected);
}
} // namespace dnn
} // namespace tk
+8 -9
View File
@@ -3,10 +3,9 @@
#include "Layer.h"
#include "kernels.h"
namespace tkDNN {
namespace tk { namespace dnn {
MulAdd::MulAdd(Network *net, dataDim_t input_dim, value_type mul, value_type add) :
Layer(net, input_dim) {
MulAdd::MulAdd(Network *net, dnnType mul, dnnType add) : Layer(net) {
this->mul = mul;
this->add = add;
@@ -14,16 +13,16 @@ MulAdd::MulAdd(Network *net, dataDim_t input_dim, value_type mul, value_type add
int size = input_dim.tot();
// create a vector with all value setted to add
value_type *add_vector_h = new value_type[size];
dnnType *add_vector_h = new dnnType[size];
for(int i=0; i<size; i++)
add_vector_h[i] = add;
checkCuda( cudaMalloc(&add_vector, size*sizeof(value_type)));
checkCuda( cudaMemcpy(add_vector, add_vector_h, size*sizeof(value_type), cudaMemcpyHostToDevice));
checkCuda( cudaMalloc(&add_vector, size*sizeof(dnnType)));
checkCuda( cudaMemcpy(add_vector, add_vector_h, size*sizeof(dnnType), cudaMemcpyHostToDevice));
delete [] add_vector_h;
checkCuda( cudaMalloc(&dstData, input_dim.tot()*sizeof(value_type)) );
checkCuda( cudaMalloc(&dstData, input_dim.tot()*sizeof(dnnType)) );
}
MulAdd::~MulAdd() {
@@ -32,7 +31,7 @@ MulAdd::~MulAdd() {
checkCuda( cudaFree(dstData) );
}
value_type* MulAdd::infer(dataDim_t &dim, value_type* srcData) {
dnnType* MulAdd::infer(dataDim_t &dim, dnnType* srcData) {
matrixMulAdd(net->cublasHandle, srcData, dstData, add_vector, input_dim.tot(), mul);
@@ -42,4 +41,4 @@ value_type* MulAdd::infer(dataDim_t &dim, value_type* srcData) {
return dstData;
}
}
}}
+127 -10
View File
@@ -1,38 +1,81 @@
#include <iostream>
#include <string.h>
#include "tkdnn.h"
#include "Network.h"
#include "Layer.h"
namespace tkDNN {
namespace tk { namespace dnn {
Network::Network() {
Network::Network(dataDim_t input_dim) {
this->input_dim = input_dim;
float tk_ver = float(tkDNN::getVersion())/1000;
float tk_ver = float(TKDNN_VERSION)/1000;
float cu_ver = float(cudnnGetVersion())/1000;
std::cout<<"New NETWORK (tkDNN v"<<tk_ver<<", CUDNN v"<<cu_ver<<")\n";
std::cout<<"New NETWORK (tkDNN v"<<tk_ver
<<", CUDNN v"<<cu_ver<<")\n";
dataType = CUDNN_DATA_FLOAT;
tensorFormat = CUDNN_TENSOR_NCHW;
dontLoadWeights = false;
num_layers = 0;
fp16 = false;
dla = false;
int8 = false;
if(const char* env_p = std::getenv("TKDNN_MODE")) {
if(strcmp(env_p, "FP16") == 0)
fp16 = true;
else if(strcmp(env_p, "DLA") == 0) {
dla = true;
fp16 = true;
}
else if(strcmp(env_p, "INT8") == 0) {
int8 = true;
}
}
maxBatchSize = 1;
if(const char* env_p = std::getenv("TKDNN_BATCHSIZE")) {
maxBatchSize = atoi(env_p);
}
if(const char* env_p = std::getenv("TKDNN_CALIB_IMG_PATH"))
fileImgList = env_p;
if(const char* env_p = std::getenv("TKDNN_CALIB_LABEL_PATH"))
fileLabelList = env_p;
if(fp16)
std::cout<<COL_REDB<<"!! FP16 INFERENCE ENABLED !!"<<COL_END<<"\n";
if(dla)
std::cout<<COL_GREENB<<"!! DLA INFERENCE ENABLED !!"<<COL_END<<"\n";
if(int8)
std::cout<<COL_ORANGEB<<"!! INT8 INFERENCE ENABLED !!"<<COL_END<<"\n";
checkCUDNN( cudnnCreate(&cudnnHandle) );
checkERROR( cublasCreate(&cublasHandle) );
num_layers = 0;
}
Network::~Network() {
checkCUDNN( cudnnDestroy(cudnnHandle) );
checkERROR( cublasDestroy(cublasHandle) );
}
value_type* Network::infer(dataDim_t &dim, value_type* data) {
void Network::releaseLayers() {
for(int i=0; i<num_layers; i++)
delete layers[i];
num_layers = 0;
}
dnnType* Network::infer(dataDim_t &dim, dnnType* data) {
//do infer for every layer
for(int i=0; i<num_layers; i++)
for(int i=0; i<num_layers; i++) {
data = layers[i]->infer(dim, data);
}
checkCuda(cudaDeviceSynchronize());
return data;
}
@@ -40,8 +83,82 @@ bool Network::addLayer(Layer *l) {
if(num_layers == MAX_LAYERS)
return false;
l->id = num_layers;
layers[num_layers++] = l;
return true;
}
}
dataDim_t Network::getOutputDim() {
if(num_layers == 0)
return input_dim;
else
return layers[num_layers-1]->output_dim;
}
void Network::print() {
printCenteredTitle(" NETWORK MODEL ", '=', 60);
std::cout.width(3); std::cout<<std::left<<"N.";
std::cout<<" ";
std::cout.width(17); std::cout<<std::left<<"Layer type";
std::cout.width(22); std::cout<<std::left<<"input (H*W,CH)";
std::cout.width(16); std::cout<<std::left<<"output (H*W,CH)";
std::cout<<"\n";
for(int i=0; i<num_layers; i++) {
dataDim_t in = layers[i]->input_dim;
dataDim_t out = layers[i]->output_dim;
std::cout.width(3); std::cout<<std::right<<i;
std::cout<<" ";
std::cout.width(16); std::cout<<std::left<<layers[i]->getLayerName();
std::cout.width(4); std::cout<<std::right<<in.h;
std::cout<<" x ";
std::cout.width(4); std::cout<<std::right<<in.w;
std::cout<<", ";
std::cout.width(4); std::cout<<std::right<<in.c;
std::cout<<" -> ";
std::cout.width(4); std::cout<<std::right<<out.h;
std::cout<<" x ";
std::cout.width(4); std::cout<<std::right<<out.w;
std::cout<<", ";
std::cout.width(4); std::cout<<std::right<<out.c;
std::cout<<"\n";
}
printCenteredTitle("", '=', 60);
std::cout<<"\n";
printCudaMemUsage();
}
const char *Network::getNetworkRTName(const char *network_name){
networkName = network_name;
int network_name_len = strlen(network_name);
char *RTName = (char *)malloc((network_name_len + 9)*sizeof(char));
if (fp16){
strcpy(RTName, network_name);
strcat(RTName, "_fp16.rt");
RTName[network_name_len + 8] = '\0';
}
else if (dla){
strcpy(RTName, network_name);
strcat(RTName, "_dla.rt");
RTName[network_name_len + 7] = '\0';
}
else if (int8){
strcpy(RTName, network_name);
strcat(RTName, "_int8.rt");
RTName[network_name_len + 8] = '\0';
}
else{
strcpy(RTName, network_name);
strcat(RTName, "_fp32.rt");
RTName[network_name_len + 8] = '\0';
}
networkNameRT = RTName;
return RTName;
}
}}
+828
View File
@@ -0,0 +1,828 @@
#include <iostream>
#include <map>
#include <errno.h>
#include <string.h> // memcpy
#include <stdlib.h>
#include "kernels.h"
#include "utils.h"
#include "NvInfer.h"
#include "NetworkRT.h"
#include "Int8Calibrator.h"
using namespace nvinfer1;
// Logger for info/warning/errors
class Logger : public ILogger {
void log(Severity severity, const char* msg) override {
#ifdef DEBUG
std::cout <<"TENSORRT LOG: "<< msg << std::endl;
#endif
}
} loggerRT;
namespace tk { namespace dnn {
std::map<Layer*, nvinfer1::ITensor*>tensors;
NetworkRT::NetworkRT(Network *net, const char *name) {
float rt_ver = float(NV_TENSORRT_MAJOR) +
float(NV_TENSORRT_MINOR)/10 +
float(NV_TENSORRT_PATCH)/100;
std::cout<<"New NetworkRT (TensorRT v"<<rt_ver<<")\n";
builderRT = createInferBuilder(loggerRT);
std::cout<<"Float16 support: "<<builderRT->platformHasFastFp16()<<"\n";
std::cout<<"Int8 support: "<<builderRT->platformHasFastInt8()<<"\n";
#if NV_TENSORRT_MAJOR >= 5
std::cout<<"DLAs: "<<builderRT->getNbDLACores()<<"\n";
#endif
networkRT = builderRT->createNetwork();
#if NV_TENSORRT_MAJOR >= 6
configRT = builderRT->createBuilderConfig();
#endif
if(!fileExist(name)) {
#if NV_TENSORRT_MAJOR >= 6
// Calibrator life time needs to last until after the engine is built.
std::unique_ptr<IInt8EntropyCalibrator> calibrator;
configRT->setAvgTimingIterations(1);
configRT->setMinTimingIterations(1);
configRT->setMaxWorkspaceSize(1 << 30);
configRT->setFlag(BuilderFlag::kDEBUG);
#endif
//input and dataType
dataDim_t dim = net->layers[0]->input_dim;
dtRT = DataType::kFLOAT;
builderRT->setMaxBatchSize(net->maxBatchSize);
builderRT->setMaxWorkspaceSize(1 << 30);
if(net->fp16 && builderRT->platformHasFastFp16()) {
dtRT = DataType::kHALF;
builderRT->setHalf2Mode(true);
#if NV_TENSORRT_MAJOR >= 6
configRT->setFlag(BuilderFlag::kFP16);
#endif
}
#if NV_TENSORRT_MAJOR >= 5
if(net->dla && builderRT->getNbDLACores() > 0) {
dtRT = DataType::kHALF;
builderRT->setFp16Mode(true);
builderRT->allowGPUFallback(true);
builderRT->setDefaultDeviceType(DeviceType::kDLA);
builderRT->setDLACore(0);
}
#endif
#if NV_TENSORRT_MAJOR >= 6
if(net->int8 && builderRT->platformHasFastInt8()){
// dtRT = DataType::kINT8;
// builderRT->setInt8Mode(true);
configRT->setFlag(BuilderFlag::kINT8);
BatchStream calibrationStream(dim, 1, 100, //TODO: check if 100 images are sufficient to the calibration (or 4951)
net->fileImgList, net->fileLabelList);
/* The calibTableFilePath contains the path+filename of the calibration table.
* Each calibration table can be found in the corresponding network folder (../Test/*).
* Each network is located in a folder with the same name as the network.
* If the folder has a different name, the calibration table is saved in build/ folder.
*/
std::string calib_table_name = net->networkName + "/" + net->networkNameRT.substr(0, net->networkNameRT.find('.')) + "-calibration.table";
std::string calib_table_path = net->networkName;
if(!fileExist((const char *)calib_table_path.c_str()))
calib_table_name = "./" + net->networkNameRT.substr(0, net->networkNameRT.find('.')) + "-calibration.table";
calibrator.reset(new Int8EntropyCalibrator(calibrationStream, 1,
calib_table_name,
"data"));
configRT->setInt8Calibrator(calibrator.get());
}
#endif
// add input layer
ITensor *input = networkRT->addInput("data", DataType::kFLOAT,
DimsCHW{ dim.c, dim.h, dim.w});
checkNULL(input);
//add other layers
for(int i=0; i<net->num_layers; i++) {
Layer *l = net->layers[i];
ILayer *Ilay = convert_layer(input, l);
#if NV_TENSORRT_MAJOR >= 6
if(net->int8 && builderRT->platformHasFastInt8())
{
Ilay->setPrecision(DataType::kINT8);
}
#endif
Ilay->setName( (l->getLayerName() + std::to_string(i)).c_str() );
input = Ilay->getOutput(0);
input->setName( (l->getLayerName() + std::to_string(i) + "_out").c_str() );
if(l->final)
networkRT->markOutput(*input);
tensors[l] = input;
}
if(input == NULL)
FatalError("conversion failed");
//build tensorRT
input->setName("out");
networkRT->markOutput(*input);
std::cout<<"Selected maxBatchSize: "<<builderRT->getMaxBatchSize()<<"\n";
printCudaMemUsage();
std::cout<<"Building tensorRT cuda engine...\n";
#if NV_TENSORRT_MAJOR >= 6
engineRT = builderRT->buildEngineWithConfig(*networkRT, *configRT);
#else
engineRT = builderRT->buildCudaEngine(*networkRT);
#endif
if(engineRT == nullptr)
FatalError("cloud not build cuda engine")
// we don't need the network any more
//networkRT->destroy();
std::cout<<"serialize net\n";
serialize(name);
} else {
deserialize(name);
}
std::cout<<"create execution context\n";
contextRT = engineRT->createExecutionContext();
// input and output buffer pointers that we pass to the engine - the engine requires exactly IEngine::getNbBindings(),
std::cout<<"Input/outputs numbers: "<<engineRT->getNbBindings()<<"\n";
if(engineRT->getNbBindings() > MAX_BUFFERS_RT)
FatalError("over RT buffer array size");
// In order to bind the buffers, we need to know the names of the input and output tensors.
// note that indices are guaranteed to be less than IEngine::getNbBindings()
buf_input_idx = engineRT->getBindingIndex("data");
buf_output_idx = engineRT->getBindingIndex("out");
std::cout<<"input idex = "<<buf_input_idx<<" -> output index = "<<buf_output_idx<<"\n";
Dims iDim = engineRT->getBindingDimensions(buf_input_idx);
input_dim.n = 1;
input_dim.c = iDim.d[0];
input_dim.h = iDim.d[1];
input_dim.w = iDim.d[2];
input_dim.print();
Dims oDim = engineRT->getBindingDimensions(buf_output_idx);
output_dim.n = 1;
output_dim.c = oDim.d[0];
output_dim.h = oDim.d[1];
output_dim.w = oDim.d[2];
output_dim.print();
// create GPU buffers and a stream
for(int i=0; i<engineRT->getNbBindings(); i++) {
Dims dim = engineRT->getBindingDimensions(i);
buffersDIM[i] = dataDim_t(1, dim.d[0], dim.d[1], dim.d[2]);
std::cout<<"RtBuffer "<<i<<" dim: "; buffersDIM[i].print();
checkCuda(cudaMalloc(&buffersRT[i], engineRT->getMaxBatchSize()*dim.d[0]*dim.d[1]*dim.d[2]*sizeof(dnnType)));
}
checkCuda(cudaMalloc(&output, engineRT->getMaxBatchSize()*output_dim.tot()*sizeof(dnnType)));
checkCuda(cudaStreamCreate(&stream));
}
NetworkRT::~NetworkRT() {
}
dnnType* NetworkRT::infer(dataDim_t &dim, dnnType* data) {
int batches = dim.n;
if(batches > getMaxBatchSize()) {
FatalError("input batch size too large");
}
checkCuda(cudaMemcpyAsync(buffersRT[buf_input_idx], data, batches*input_dim.tot()*sizeof(dnnType), cudaMemcpyDeviceToDevice, stream));
contextRT->enqueue(batches, buffersRT, stream, nullptr);
checkCuda(cudaMemcpyAsync(output, buffersRT[buf_output_idx], batches*output_dim.tot()*sizeof(dnnType), cudaMemcpyDeviceToDevice, stream));
checkCuda(cudaStreamSynchronize(stream));
dim = output_dim;
dim.n = batches;
return output;
}
void NetworkRT::enqueue(int batchSize) {
contextRT->enqueue(batchSize, buffersRT, stream, nullptr);
}
ILayer* NetworkRT::convert_layer(ITensor *input, Layer *l) {
layerType_t type = l->getLayerType();
if(type == LAYER_DENSE)
return convert_layer(input, (Dense*) l);
if(type == LAYER_CONV2D || type == LAYER_DECONV2D)
return convert_layer(input, (Conv2d*) l);
if(type == LAYER_POOLING)
return convert_layer(input, (Pooling*) l);
if(type == LAYER_ACTIVATION || type == LAYER_ACTIVATION_CRELU || type == LAYER_ACTIVATION_LEAKY || type == LAYER_ACTIVATION_MISH)
return convert_layer(input, (Activation*) l);
if(type == LAYER_SOFTMAX)
return convert_layer(input, (Softmax*) l);
if(type == LAYER_ROUTE)
return convert_layer(input, (Route*) l);
if(type == LAYER_FLATTEN)
return convert_layer(input, (Flatten*) l);
if(type == LAYER_RESHAPE)
return convert_layer(input, (Reshape*) l);
if(type == LAYER_REORG)
return convert_layer(input, (Reorg*) l);
if(type == LAYER_REGION)
return convert_layer(input, (Region*) l);
if(type == LAYER_SHORTCUT)
return convert_layer(input, (Shortcut*) l);
if(type == LAYER_YOLO)
return convert_layer(input, (Yolo*) l);
if(type == LAYER_UPSAMPLE)
return convert_layer(input, (Upsample*) l);
if(type == LAYER_DEFORMCONV2D)
return convert_layer(input, (DeformConv2d*) l);
std::cout<<l->getLayerName()<<"\n";
FatalError("Layer not implemented in tensorRT");
return NULL;
}
ILayer* NetworkRT::convert_layer(ITensor *input, Dense *l) {
//std::cout<<"convert Dense\n";
void *data_b, *bias_b;
if(dtRT == DataType::kHALF) {
data_b = l->data16_h;
bias_b = l->bias16_h;
} else {
data_b = l->data_h;
bias_b = l->bias_h;
}
Weights w { dtRT, data_b, l->inputs*l->outputs};
Weights b = { dtRT, bias_b, l->outputs};
IFullyConnectedLayer *lRT = networkRT->addFullyConnected(*input, l->outputs, w, b);
checkNULL(lRT);
return lRT;
}
ILayer* NetworkRT::convert_layer(ITensor *input, Conv2d *l) {
// std::cout<<"convert conv2D\n";
// printf("%d %d %d %d %d\n", l->kernelH, l->kernelW, l->inputs, l->outputs, l->batchnorm);
void *data_b, *bias_b, *bias2_b, *power_b, *mean_b, *variance_b, *scales_b;
if(dtRT == DataType::kHALF) {
data_b = l->data16_h;
bias_b = l->bias16_h;
bias2_b = l->bias216_h;
power_b = l->power16_h;
mean_b = l->mean16_h;
variance_b = l->variance16_h;
scales_b = l->scales16_h;
} else {
data_b = l->data_h;
bias_b = l->bias_h;
bias2_b = l->bias2_h;
power_b = l->power_h;
mean_b = l->mean_h;
variance_b = l->variance_h;
scales_b = l->scales_h;
}
Weights w { dtRT, data_b, l->inputs*l->outputs*l->kernelH*l->kernelW};
Weights b;
if(!l->batchnorm)
b = { dtRT, bias_b, l->outputs};
else{
if (l->additional_bias)
b = { dtRT, bias2_b, l->outputs};
else
b = { dtRT, nullptr, 0}; //on batchnorm bias are added later
}
ILayer *lRT = nullptr;
if(!l->deConv) {
IConvolutionLayer *lRTconv = networkRT->addConvolution(*input,
l->outputs, DimsHW{l->kernelH, l->kernelW}, w, b);
checkNULL(lRTconv);
lRTconv->setStride(DimsHW{l->strideH, l->strideW});
lRTconv->setPadding(DimsHW{l->paddingH, l->paddingW});
lRTconv->setNbGroups(l->groups);
lRT = (ILayer*) lRTconv;
} else {
IDeconvolutionLayer *lRTconv = networkRT->addDeconvolution(*input,
l->outputs, DimsHW{l->kernelH, l->kernelW}, w, b);
checkNULL(lRTconv);
lRTconv->setStride(DimsHW{l->strideH, l->strideW});
lRTconv->setPadding(DimsHW{l->paddingH, l->paddingW});
lRTconv->setNbGroups(l->groups);
lRT = (ILayer*) lRTconv;
Dims d = lRTconv->getOutput(0)->getDimensions();
//std::cout<<"DECONV: "<<d.d[0]<<" "<<d.d[1]<<" "<<d.d[2]<<" "<<d.d[3]<<"\n";
}
checkNULL(lRT);
if(l->batchnorm) {
Weights power{dtRT, power_b, l->outputs};
Weights shift{dtRT, mean_b, l->outputs};
Weights scale{dtRT, variance_b, l->outputs};
// std::cout<<lRT->getNbOutputs()<<std::endl;
IScaleLayer *lRT2 = networkRT->addScale(*lRT->getOutput(0), ScaleMode::kCHANNEL,
shift, scale, power);
checkNULL(lRT2);
Weights shift2{dtRT, bias_b, l->outputs};
Weights scale2{dtRT, scales_b, l->outputs};
IScaleLayer *lRT3 = networkRT->addScale(*lRT2->getOutput(0), ScaleMode::kCHANNEL,
shift2, scale2, power);
checkNULL(lRT3);
return lRT3;
}
return lRT;
}
ILayer* NetworkRT::convert_layer(ITensor *input, Pooling *l) {
// std::cout<<"convert Pooling\n";
PoolingType ptype;
if(l->pool_mode == tkdnnPoolingMode_t::POOLING_MAX) ptype = PoolingType::kMAX;
if(l->pool_mode == tkdnnPoolingMode_t::POOLING_AVERAGE) ptype = PoolingType::kAVERAGE;
if(l->pool_mode == tkdnnPoolingMode_t::POOLING_AVERAGE_EXCLUDE_PADDING) ptype = PoolingType::kMAX_AVERAGE_BLEND;
if(l->pool_mode == tkdnnPoolingMode_t::POOLING_MAX_FIXEDSIZE)
{
IPlugin *plugin = new MaxPoolFixedSizeRT(l->output_dim.c, l->output_dim.h, l->output_dim.w, l->output_dim.n, l->strideH, l->strideW, l->winH, l->winH-1);
IPluginLayer *lRT = networkRT->addPlugin(&input, 1, *plugin);
checkNULL(lRT);
return lRT;
}
else
{
IPoolingLayer *lRT = networkRT->addPooling(*input, ptype, DimsHW{l->winH, l->winW});
checkNULL(lRT);
lRT->setPadding(DimsHW{l->paddingH, l->paddingW});
lRT->setStride(DimsHW{l->strideH, l->strideW});
return lRT;
}
}
ILayer* NetworkRT::convert_layer(ITensor *input, Activation *l) {
//std::cout<<"convert Activation\n";
if(l->act_mode == ACTIVATION_LEAKY) {
//std::cout<<"New plugin LEAKY\n";
#if NV_TENSORRT_MAJOR < 6
// plugin version
IPlugin *plugin = new ActivationLeakyRT();
IPluginLayer *lRT = networkRT->addPlugin(&input, 1, *plugin);
checkNULL(lRT);
return lRT;
#else
IActivationLayer *lRT = networkRT->addActivation(*input, ActivationType::kLEAKY_RELU);
lRT->setAlpha(0.1);
checkNULL(lRT);
return lRT;
#endif
} else if(l->act_mode == CUDNN_ACTIVATION_RELU) {
IActivationLayer *lRT = networkRT->addActivation(*input, ActivationType::kRELU);
checkNULL(lRT);
return lRT;
} else if(l->act_mode == CUDNN_ACTIVATION_SIGMOID) {
IActivationLayer *lRT = networkRT->addActivation(*input, ActivationType::kSIGMOID);
checkNULL(lRT);
return lRT;
}
else if(l->act_mode == CUDNN_ACTIVATION_CLIPPED_RELU) {
IPlugin *plugin = new ActivationReLUCeiling(l->ceiling);
IPluginLayer *lRT = networkRT->addPlugin(&input, 1, *plugin);
checkNULL(lRT);
return lRT;
}
else if(l->act_mode == ACTIVATION_MISH) {
IPlugin *plugin = new ActivationMishRT();
IPluginLayer *lRT = networkRT->addPlugin(&input, 1, *plugin);
checkNULL(lRT);
return lRT;
}
else {
FatalError("this Activation mode is not yet implemented");
return NULL;
}
}
ILayer* NetworkRT::convert_layer(ITensor *input, Softmax *l) {
//std::cout<<"convert softmax\n";
ISoftMaxLayer *lRT = networkRT->addSoftMax(*input);
checkNULL(lRT);
return lRT;
}
ILayer* NetworkRT::convert_layer(ITensor *input, Route *l) {
// std::cout<<"convert route\n";
ITensor **tens = new ITensor*[l->layers_n];
for(int i=0; i<l->layers_n; i++) {
tens[i] = tensors[l->layers[i]];
// for(int j=0; j<tens[i]->getDimensions().nbDims; j++) {
// std::cout<<tens[i]->getDimensions().d[j]<<" ";
// }
// std::cout<<"\n";
}
if(l->groups > 1){
IPlugin *plugin = new RouteRT(l->groups, l->group_id);
IPluginLayer *lRT = networkRT->addPlugin(tens, l->layers_n, *plugin);
checkNULL(lRT);
return lRT;
}
IConcatenationLayer *lRT = networkRT->addConcatenation(tens, l->layers_n);
checkNULL(lRT);
return lRT;
}
ILayer* NetworkRT::convert_layer(ITensor *input, Flatten *l) {
IPlugin *plugin = new FlattenConcatRT();
IPluginLayer *lRT = networkRT->addPlugin(&input, 1, *plugin);
checkNULL(lRT);
return lRT;
}
ILayer* NetworkRT::convert_layer(ITensor *input, Reshape *l) {
// std::cout<<"convert Reshape\n";
l->output_dim.print();
IPlugin *plugin = new ReshapeRT(l->output_dim);
IPluginLayer *lRT = networkRT->addPlugin(&input, 1, *plugin);
checkNULL(lRT);
return lRT;
}
ILayer* NetworkRT::convert_layer(ITensor *input, Reorg *l) {
//std::cout<<"convert Reorg\n";
//std::cout<<"New plugin REORG\n";
IPlugin *plugin = new ReorgRT(l->stride);
IPluginLayer *lRT = networkRT->addPlugin(&input, 1, *plugin);
checkNULL(lRT);
return lRT;
}
ILayer* NetworkRT::convert_layer(ITensor *input, Region *l) {
//std::cout<<"convert Region\n";
//std::cout<<"New plugin REGION\n";
IPlugin *plugin = new RegionRT(l->classes, l->coords, l->num);
IPluginLayer *lRT = networkRT->addPlugin(&input, 1, *plugin);
checkNULL(lRT);
return lRT;
}
ILayer* NetworkRT::convert_layer(ITensor *input, Shortcut *l) {
//std::cout<<"convert Shortcut\n";
//std::cout<<"New plugin Shortcut\n";
ITensor *back_tens = tensors[l->backLayer];
if(l->backLayer->output_dim.c == l->output_dim.c)
{
IElementWiseLayer *lRT = networkRT->addElementWise(*input, *back_tens, ElementWiseOperation::kSUM);
checkNULL(lRT);
return lRT;
}
else
{
// plugin version
IPlugin *plugin = new ShortcutRT(l->backLayer->output_dim);
ITensor **inputs = new ITensor*[2];
inputs[0] = input;
inputs[1] = back_tens;
IPluginLayer *lRT = networkRT->addPlugin(inputs, 2, *plugin);
checkNULL(lRT);
return lRT;
}
}
ILayer* NetworkRT::convert_layer(ITensor *input, Yolo *l) {
//std::cout<<"convert Yolo\n";
//std::cout<<"New plugin YOLO\n";
IPlugin *plugin = new YoloRT(l->classes, l->num, l, l->n_masks, l->scaleXY);
IPluginLayer *lRT = networkRT->addPlugin(&input, 1, *plugin);
checkNULL(lRT);
return lRT;
}
ILayer* NetworkRT::convert_layer(ITensor *input, Upsample *l) {
//std::cout<<"convert Upsample\n";
//std::cout<<"New plugin UPSAMPLE\n";
IPlugin *plugin = new UpsampleRT(l->stride);
IPluginLayer *lRT = networkRT->addPlugin(&input, 1, *plugin);
checkNULL(lRT);
return lRT;
}
ILayer* NetworkRT::convert_layer(ITensor *input, DeformConv2d *l) {
//std::cout<<"convert DEFORMABLE\n";
ILayer *preconv = convert_layer(input, l->preconv);
checkNULL(preconv);
ITensor **inputs = new ITensor*[2];
inputs[0] = input;
inputs[1] = preconv->getOutput(0);
//std::cout<<"New plugin DEFORMABLE\n";
IPlugin *plugin = new DeformableConvRT(l->chunk_dim, l->kernelH, l->kernelW, l->strideH, l->strideW, l->paddingH, l->paddingW,
l->deformableGroup, l->input_dim.n, l->input_dim.c, l->input_dim.h, l->input_dim.w,
l->output_dim.n, l->output_dim.c, l->output_dim.h, l->output_dim.w, l);
IPluginLayer *lRT = networkRT->addPlugin(inputs, 2, *plugin);
checkNULL(lRT);
lRT->setName( ("Deformable" + std::to_string(l->id)).c_str() );
delete(inputs);
// batchnorm
void *bias_b, *power_b, *mean_b, *variance_b, *scales_b;
if(dtRT == DataType::kHALF) {
bias_b = l->bias16_h;
power_b = l->power16_h;
mean_b = l->mean16_h;
variance_b = l->variance16_h;
scales_b = l->scales16_h;
} else {
bias_b = l->bias_h;
power_b = l->power_h;
mean_b = l->mean_h;
variance_b = l->variance_h;
scales_b = l->scales_h;
}
Weights power{dtRT, power_b, l->outputs};
Weights shift{dtRT, mean_b, l->outputs};
Weights scale{dtRT, variance_b, l->outputs};
//std::cout<<lRT->getNbOutputs()<<std::endl;
IScaleLayer *lRT2 = networkRT->addScale(*lRT->getOutput(0), ScaleMode::kCHANNEL,
shift, scale, power);
checkNULL(lRT2);
Weights shift2{dtRT, bias_b, l->outputs};
Weights scale2{dtRT, scales_b, l->outputs};
IScaleLayer *lRT3 = networkRT->addScale(*lRT2->getOutput(0), ScaleMode::kCHANNEL,
shift2, scale2, power);
checkNULL(lRT3);
return lRT3;
}
bool NetworkRT::serialize(const char *filename) {
std::ofstream p(filename, std::ios::binary);
if (!p) {
FatalError("could not open plan output file");
return false;
}
IHostMemory *ptr = engineRT->serialize();
if(ptr == nullptr)
FatalError("Cant serialize network");
p.write(reinterpret_cast<const char*>(ptr->data()), ptr->size());
ptr->destroy();
return true;
}
bool NetworkRT::deserialize(const char *filename) {
char *gieModelStream{nullptr};
size_t size{0};
std::ifstream file(filename, std::ios::binary);
if (file.good()) {
file.seekg(0, file.end);
size = file.tellg();
file.seekg(0, file.beg);
gieModelStream = new char[size];
file.read(gieModelStream, size);
file.close();
}
pluginFactory = new PluginFactory();
runtimeRT = createInferRuntime(loggerRT);
engineRT = runtimeRT->deserializeCudaEngine(gieModelStream, size, (IPluginFactory *) pluginFactory);
//if (gieModelStream) delete [] gieModelStream;
return true;
}
IPlugin* PluginFactory::createPlugin(const char* layerName, const void* serialData, size_t serialLength) {
const char * buf = reinterpret_cast<const char*>(serialData);
std::string name(layerName);
//std::cout<<name<<std::endl;
if(name.find("ActivationLeaky") == 0) {
ActivationLeakyRT *a = new ActivationLeakyRT();
a->size = readBUF<int>(buf);
return a;
}
if(name.find("ActivationMish") == 0) {
ActivationMishRT *a = new ActivationMishRT();
a->size = readBUF<int>(buf);
return a;
}
if(name.find("ActivationCReLU") == 0) {
ActivationReLUCeiling *a = new ActivationReLUCeiling(readBUF<float>(buf));
a->size = readBUF<int>(buf);
return a;
}
if(name.find("Region") == 0) {
RegionRT *r = new RegionRT(readBUF<int>(buf), //classes
readBUF<int>(buf), //coords
readBUF<int>(buf)); //num
r->c = readBUF<int>(buf);
r->h = readBUF<int>(buf);
r->w = readBUF<int>(buf);
return r;
}
if(name.find("Reorg") == 0) {
ReorgRT *r = new ReorgRT(readBUF<int>(buf)); //stride
r->c = readBUF<int>(buf);
r->h = readBUF<int>(buf);
r->w = readBUF<int>(buf);
return r;
}
if(name.find("Shortcut") == 0) {
tk::dnn::dataDim_t bdim;
bdim.c = readBUF<int>(buf);
bdim.h = readBUF<int>(buf);
bdim.w = readBUF<int>(buf);
bdim.l = 1;
ShortcutRT *r = new ShortcutRT(bdim);
r->c = readBUF<int>(buf);
r->h = readBUF<int>(buf);
r->w = readBUF<int>(buf);
return r;
}
if(name.find("Pooling") == 0) {
MaxPoolFixedSizeRT *r = new MaxPoolFixedSizeRT( readBUF<int>(buf), //c
readBUF<int>(buf), //h
readBUF<int>(buf), //w
readBUF<int>(buf), //n
readBUF<int>(buf), //strideH
readBUF<int>(buf), //strideW
readBUF<int>(buf), //winSize
readBUF<int>(buf)); //padding
return r;
}
if(name.find("Resize") == 0) {
ResizeLayerRT *r = new ResizeLayerRT(readBUF<int>(buf), //o_c
readBUF<int>(buf), //o_h
readBUF<int>(buf)); //o_w
r->i_c = readBUF<int>(buf);
r->i_h = readBUF<int>(buf);
r->i_w = readBUF<int>(buf);
return r;
}
if(name.find("Flatten") == 0) {
FlattenConcatRT *r = new FlattenConcatRT();
r->c = readBUF<int>(buf);
r->h = readBUF<int>(buf);
r->w = readBUF<int>(buf);
r->rows = readBUF<int>(buf);
r->cols = readBUF<int>(buf);
return r;
}
if(name.find("Reshape") == 0) {
dataDim_t new_dim;
new_dim.n = readBUF<int>(buf);
new_dim.c = readBUF<int>(buf);
new_dim.h = readBUF<int>(buf);
new_dim.w = readBUF<int>(buf);
ReshapeRT *r = new ReshapeRT(new_dim);
return r;
}
if(name.find("Yolo") == 0) {
YoloRT *r = new YoloRT(readBUF<int>(buf), //classes
readBUF<int>(buf), //num
nullptr,
readBUF<int>(buf)); //n_masks
r->c = readBUF<int>(buf);
r->h = readBUF<int>(buf);
r->w = readBUF<int>(buf);
r->scaleXY = readBUF<float>(buf);
for(int i=0; i<r->n_masks; i++)
r->mask[i] = readBUF<dnnType>(buf);
for(int i=0; i<r->n_masks*2*r->num; i++)
r->bias[i] = readBUF<dnnType>(buf);
// save classes names
r->classesNames.resize(r->classes);
for(int i=0; i<r->classes; i++) {
char tmp[YOLORT_CLASSNAME_W];
for(int j=0; j<YOLORT_CLASSNAME_W; j++)
tmp[j] = readBUF<char>(buf);
r->classesNames[i] = std::string(tmp);
}
yolos[n_yolos++] = r;
return r;
}
if(name.find("Upsample") == 0) {
UpsampleRT *r = new UpsampleRT(readBUF<int>(buf)); //stride
r->c = readBUF<int>(buf);
r->h = readBUF<int>(buf);
r->w = readBUF<int>(buf);
return r;
}
if(name.find("Route") == 0) {
RouteRT *r = new RouteRT(readBUF<int>(buf),readBUF<int>(buf));
r->in = readBUF<int>(buf);
for(int i=0; i<RouteRT::MAX_INPUTS; i++)
r->c_in[i] = readBUF<int>(buf);
r->c = readBUF<int>(buf);
r->h = readBUF<int>(buf);
r->w = readBUF<int>(buf);
return r;
}
if(name.find("Deformable") == 0) {
DeformableConvRT *r = new DeformableConvRT(readBUF<int>(buf), readBUF<int>(buf), readBUF<int>(buf),
readBUF<int>(buf), readBUF<int>(buf), readBUF<int>(buf),
readBUF<int>(buf), readBUF<int>(buf),
readBUF<int>(buf),readBUF<int>(buf),readBUF<int>(buf),readBUF<int>(buf),
readBUF<int>(buf),readBUF<int>(buf),readBUF<int>(buf),readBUF<int>(buf),
nullptr);
dnnType *aus = new dnnType[r->chunk_dim*2];
for(int i=0; i<r->chunk_dim*2; i++)
aus[i] = readBUF<dnnType>(buf);
checkCuda( cudaMemcpy(r->offset, aus, sizeof(dnnType)*2*r->chunk_dim, cudaMemcpyHostToDevice) );
free(aus);
aus = new dnnType[r->chunk_dim];
for(int i=0; i<r->chunk_dim; i++)
aus[i] = readBUF<dnnType>(buf);
checkCuda( cudaMemcpy(r->mask, aus, sizeof(dnnType)*r->chunk_dim, cudaMemcpyHostToDevice) );
free(aus);
aus = new dnnType[(r->i_c * r->o_c * r->kh * r->kw * 1 )];
for(int i=0; i<(r->i_c * r->o_c * r->kh * r->kw * 1 ); i++)
aus[i] = readBUF<dnnType>(buf);
checkCuda( cudaMemcpy(r->data_d, aus, sizeof(dnnType)*(r->i_c * r->o_c * r->kh * r->kw * 1 ), cudaMemcpyHostToDevice) );
free(aus);
aus = new dnnType[r->o_c];
for(int i=0; i < r->o_c; i++)
aus[i] = readBUF<dnnType>(buf);
checkCuda( cudaMemcpy(r->bias2_d, aus, sizeof(dnnType)*r->o_c, cudaMemcpyHostToDevice) );
free(aus);
aus = new dnnType[r->height_ones * r->width_ones];
for(int i=0; i<r->height_ones * r->width_ones; i++)
aus[i] = readBUF<dnnType>(buf);
checkCuda( cudaMemcpy(r->ones_d1, aus, sizeof(dnnType)*r->height_ones * r->width_ones, cudaMemcpyHostToDevice) );
free(aus);
aus = new dnnType[r->dim_ones];
for(int i=0; i<r->dim_ones; i++)
aus[i] = readBUF<dnnType>(buf);
checkCuda( cudaMemcpy(r->ones_d2, aus, sizeof(dnnType)*r->dim_ones, cudaMemcpyHostToDevice) );
free(aus);
return r;
}
FatalError("Cant deserialize Plugin");
return NULL;
}
}}
+69
View File
@@ -0,0 +1,69 @@
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/videoio.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include "tkDNN/NetworkViz.h"
namespace tk { namespace dnn {
cv::Mat vizFloat2colorMap(cv::Mat map) {
double min;
double max;
cv::minMaxIdx(map, &min, &max);
cv::Mat adjMap;
// expand your range to 0..255. Similar to histEq();
map.convertTo(adjMap,CV_8UC1, 255 / (max-min), -min);
//return adjMap;
cv::Mat falseColorsMap;
applyColorMap(adjMap, falseColorsMap, cv::COLORMAP_HOT);
return falseColorsMap;
}
cv::Mat vizData2Mat(dnnType *dataInput, tk::dnn::dataDim_t dim, int imgdim) {
dnnType *data = nullptr;
// copy to CPU
if(isCudaPointer(dataInput)) {
data = new dnnType[dim.tot()];
checkCuda( cudaMemcpy(data, dataInput, dim.tot()*sizeof(dnnType), cudaMemcpyDeviceToHost) );
} else {
data = dataInput;
}
int gridDim = ceil(sqrt(dim.c));
cv::Size gridSize(dim.w*gridDim, dim.h*gridDim);
cv::Mat grid = cv::Mat(gridSize, CV_8UC3, cv::Scalar(0));
for(int i=0; i<dim.c;i++) {
cv::Mat raw = vizFloat2colorMap(cv::Mat(cv::Size(dim.w, dim.h),CV_32FC1, data + dim.w*dim.h*i));
int r = i / gridDim;
int c = i - r * gridDim;
raw.copyTo(grid.rowRange(r*dim.h, r*dim.h + dim.h).colRange(c*dim.w, c*dim.w + dim.w));
}
float ar = float(dim.w)/dim.h;
cv::Size vdim(ar*imgdim, imgdim);
cv::Mat viz;
cv::resize(grid, viz, vdim, 0, 0, 0);
// free memory
if(isCudaPointer(dataInput)) {
delete [] data;
}
return viz;
}
cv::Mat vizLayer2Mat(tk::dnn::Network *net, int layer, int imgdim) {
if(layer >= net->num_layers)
FatalError("Could not viz layer\n");
return vizData2Mat(net->layers[layer]->dstData, net->layers[layer]->output_dim, imgdim);
//cv::imwrite("viz/layer" + std::to_string(layer) + ".png", viz);
//cv::imshow("layer", viz);
//cv::waitKey(0);
}
}}
+47 -25
View File
@@ -3,22 +3,21 @@
#include "Layer.h"
#include "kernels.h"
namespace tkDNN {
namespace tk { namespace dnn {
Pooling::Pooling( Network *net, dataDim_t input_dim,
int winH, int winW, int strideH, int strideW, tkdnnPoolingMode_t pool_mode) :
Layer(net, input_dim) {
if(winH != strideH || winW != strideW)
FatalError("stride pooling not yet implemented");
Pooling::Pooling( Network *net, int winH, int winW, int strideH, int strideW,
int paddingH, int paddingW,
tkdnnPoolingMode_t pool_mode) :
Layer(net) {
this->winH = winH;
this->winW = winW;
this->strideH = strideH;
this->strideW = strideW;
this->pool_mode = pool_mode;
this->paddingH = paddingH;
this->paddingW = paddingW;
checkCUDNN( cudnnCreatePoolingDescriptor(&poolingDesc) );
int n = input_dim.n;
@@ -26,6 +25,7 @@ Pooling::Pooling( Network *net, dataDim_t input_dim,
int h = input_dim.h;
int w = input_dim.w;
int l = input_dim.l;
poolOn3d = false;
@@ -39,34 +39,51 @@ Pooling::Pooling( Network *net, dataDim_t input_dim,
n = l;
}
checkCUDNN( cudnnSetPooling2dDescriptor(poolingDesc, cudnnPoolingMode_t(pool_mode),
CUDNN_NOT_PROPAGATE_NAN, winH, winW, 0, 0, strideH, strideW) );
cudnnPoolingMode_t cudnn_pool_mode = cudnnPoolingMode_t(pool_mode);
if(pool_mode == POOLING_MAX_FIXEDSIZE) cudnn_pool_mode = cudnnPoolingMode_t(tkdnnPoolingMode_t::POOLING_MAX);
checkCUDNN( cudnnSetPooling2dDescriptor(poolingDesc, cudnn_pool_mode,
CUDNN_NOT_PROPAGATE_NAN, winH, winW, paddingH, paddingW, strideH, strideW) );
checkCUDNN( cudnnSetTensor4dDescriptor(srcTensorDesc,
net->tensorFormat, net->dataType, n, c, h, w) );
//get out dim
h = h / winH; w = w / winW;
// checkCUDNN( cudnnGetPooling2dForwardOutputDim(poolingDesc, srcTensorDesc, &n, &c, &h, &w));
//compute w and h as in darknet
if(pool_mode == tkdnnPoolingMode_t::POOLING_MAX_FIXEDSIZE){
int padH = paddingH == 0? winH -1 : paddingH;
int padW = paddingW == 0? winW -1 : paddingW;
h = (h + padH - winH)/strideH +1;
w = (w + padW - winW)/strideW +1;
}
else{
h = (h + 2*paddingH - winH)/strideH +1 ;
w = (w + 2*paddingW - winW)/strideW +1;
}
// h = (h + winH*this->paddingH)/strideH;
// w = (w + winW*this->paddingW)/strideW;
checkCUDNN( cudnnSetTensor4dDescriptor(dstTensorDesc,
net->tensorFormat, net->dataType, n, c, h, w) );
output_dim.n = n;
output_dim.c = c;
output_dim.h = h;
output_dim.w = w;
output_dim.l = l;
checkCuda( cudaMalloc(&dstData, output_dim.tot()*sizeof(value_type)) );
checkCuda( cudaMalloc(&dstData, output_dim.tot()*sizeof(dnnType)) );
//pool on 3d data need transposition at the enter and on the exit
//allocate for initial and final transposition
if(poolOn3d) {
output_dim.n = 1;
checkCuda( cudaMalloc(&tmpInputData, input_dim.tot()*sizeof(value_type)) );
checkCuda( cudaMalloc(&tmpOutputData, output_dim.tot()*sizeof(value_type)) );
checkCuda( cudaMalloc(&tmpInputData, input_dim.tot()*sizeof(dnnType)) );
checkCuda( cudaMalloc(&tmpOutputData, output_dim.tot()*sizeof(dnnType)) );
}
}
@@ -82,10 +99,10 @@ Pooling::~Pooling() {
checkCuda( cudaFree(dstData) );
}
value_type* Pooling::infer(dataDim_t &dim, value_type* srcData) {
dnnType* Pooling::infer(dataDim_t &dim, dnnType* srcData) {
value_type *poolSrc = srcData;
value_type *poolDst = dstData;
dnnType *poolSrc = srcData;
dnnType *poolDst = dstData;
if(poolOn3d) {
matrixTranspose(net->cublasHandle, srcData, tmpInputData, dim.h*dim.w*dim.c, dim.l);
@@ -93,11 +110,16 @@ value_type* Pooling::infer(dataDim_t &dim, value_type* srcData) {
poolDst = tmpOutputData;
}
value_type alpha = value_type(1);
value_type beta = value_type(0);
checkCUDNN( cudnnPoolingForward(net->cudnnHandle, poolingDesc,
&alpha, srcTensorDesc, poolSrc,
&beta, dstTensorDesc, poolDst) );
if(pool_mode == tkdnnPoolingMode_t::POOLING_MAX_FIXEDSIZE){
MaxPoolingForward(poolSrc, poolDst, dim.n, dim.c, dim.h, dim.w, this->strideH, this->strideW, this->winH, this->winH-1);
}
else{
dnnType alpha = dnnType(1);
dnnType beta = dnnType(0);
checkCUDNN( cudnnPoolingForward(net->cudnnHandle, poolingDesc,
&alpha, srcTensorDesc, poolSrc,
&beta, dstTensorDesc, poolDst) );
}
//update dim
dim = output_dim;
@@ -108,4 +130,4 @@ value_type* Pooling::infer(dataDim_t &dim, value_type* srcData) {
return dstData;
}
}
}}
+341
View File
@@ -0,0 +1,341 @@
#include <iostream>
#ifdef OPENCV
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#endif
#include "Layer.h"
#include "kernels.h"
namespace tk { namespace dnn {
Region::Region(Network *net, int classes, int coords, int num) :
Layer(net) {
this->classes = classes;
this->coords = coords;
this->num = num;
// same
output_dim.n = input_dim.n;
output_dim.c = input_dim.c;
output_dim.h = input_dim.h;
output_dim.w = input_dim.w;
output_dim.l = input_dim.l;
checkCuda( cudaMalloc(&dstData, output_dim.tot()*sizeof(dnnType)) );
}
Region::~Region() {
checkCuda( cudaFree(dstData) );
}
int entry_index(int batch, int location, int entry,
int coords, int classes, dataDim_t &input_dim, dataDim_t &output_dim) {
int n = location / (input_dim.w*input_dim.h);
int loc = location % (input_dim.w*input_dim.h);
return batch*output_dim.tot() + n*input_dim.w*input_dim.h*(coords+classes+1) +
entry*input_dim.w*input_dim.h + loc;
}
dnnType* Region::infer(dataDim_t &dim, dnnType* srcData) {
checkCuda( cudaMemcpy(dstData, srcData, dim.tot()*sizeof(dnnType), cudaMemcpyDeviceToDevice));
for (int b = 0; b < dim.n; ++b){
for(int n = 0; n < num; ++n){
int index = entry_index(b, n*dim.w*dim.h, 0, coords, classes, input_dim, output_dim);
activationLOGISTICForward(srcData + index, dstData + index, 2*dim.w*dim.h);
index = entry_index(b, n*dim.w*dim.h, coords, coords, classes, input_dim, output_dim);
activationLOGISTICForward(srcData + index, dstData + index, dim.w*dim.h);
}
}
//softmax start
int index = entry_index(0, 0, coords + 1, coords, classes, input_dim, output_dim);
softmaxForward(srcData + index, classes, output_dim.n*num, output_dim.tot()/num,
output_dim.w*output_dim.h, 1, output_dim.w*output_dim.h, 1, dstData + index);
dim = output_dim;
return dstData;
}
/* Intepret class */
RegionInterpret::RegionInterpret(dataDim_t input_dim, dataDim_t output_dim,
int classes, int coords, int num, float thresh, std::string fname_weights) {
this->input_dim = input_dim;
this->output_dim = output_dim;
this->classes = classes;
this->coords = coords;
this->num = num;
this->thresh = thresh;
this->res_boxes_n = 0;
int tot = output_dim.w*output_dim.h*num;
boxes = (box*) malloc(tot*sizeof(box));
probs = (float**) malloc(tot*sizeof(float *));
for(int j = 0; j < tot; ++j) probs[j] = (float*) malloc((classes + 1)*sizeof(float *));
s = (sortable_bbox*) malloc(tot*sizeof(sortable_bbox));
//load anchors
readBinaryFile(fname_weights, 2*num, &bias_h, &bias_d);
}
RegionInterpret::~RegionInterpret() {
delete [] boxes;
for(int j = 0; j < output_dim.w*output_dim.h*num; ++j)
delete [] probs[j];
delete [] probs;
delete [] s;
delete [] bias_h;
checkCuda( cudaFree(bias_d) );
}
box RegionInterpret::get_region_box(float *x, float *biases, int n, int index, int i, int j, int w, int h, int stride)
{
box b;
b.x = (i + x[index + 0*stride]) / w;
b.y = (j + x[index + 1*stride]) / h;
b.w = exp(x[index + 2*stride]) * biases[2*n] / w;
b.h = exp(x[index + 3*stride]) * biases[2*n+1] / h;
return b;
}
void RegionInterpret::get_region_boxes( float *input, int w, int h, int netw, int neth, float thresh,
float **probs, box *boxes, int only_objectness,
int *map, float tree_thresh, int relative) {
int lh = output_dim.h;
int lw = output_dim.w;
float *predictions = input;
for (int i = 0; i < lw*lh; ++i){
int row = i / lw;
int col = i % lw;
for(int n = 0; n < num; ++n){
int index = n*lw*lh + i;
for(int j = 0; j < classes; ++j){
probs[index][j] = 0;
}
int obj_index = entry_index(0, n*lw*lh + i,
coords, coords, classes, output_dim, output_dim);
int box_index = entry_index(0, n*lw*lh + i, 0,
coords, classes, output_dim, output_dim);
float scale = predictions[obj_index];
boxes[index] = get_region_box(predictions, bias_h, n, box_index, col, row, lw, lh, lw*lh);
float max = 0;
for(int j = 0; j < classes; ++j){
int class_index = entry_index(0, n*lw*lh + i, coords + 1 + j,
coords, classes, output_dim, output_dim);
float prob = scale*predictions[class_index];
probs[index][j] = (prob > thresh) ? prob : 0;
if(prob > max) max = prob;
}
probs[index][classes] = max;
}
}
correct_region_boxes(boxes, lw*lh*num, w, h, netw, neth, relative);
}
void RegionInterpret::correct_region_boxes(box *boxes, int n, int w, int h, int netw, int neth, int relative) {
int i;
int new_w=0;
int new_h=0;
if (((float)netw/w) < ((float)neth/h)) {
new_w = netw;
new_h = (h * netw)/w;
} else {
new_h = neth;
new_w = (w * neth)/h;
}
for (i = 0; i < n; ++i){
box b = boxes[i];
b.x = (b.x - (netw - new_w)/2./netw) / ((float)new_w/netw);
b.y = (b.y - (neth - new_h)/2./neth) / ((float)new_h/neth);
b.w *= (float)netw/new_w;
b.h *= (float)neth/new_h;
if(!relative){
b.x *= w;
b.w *= w;
b.y *= h;
b.h *= h;
}
boxes[i] = b;
}
}
//############################ BOX PROBABILITY UTILS ############################
int nms_comparator(const void *pa, const void *pb) {
sortable_bbox a = *(sortable_bbox *)pa;
sortable_bbox b = *(sortable_bbox *)pb;
float diff = a.probs[a.index][b.cl] - b.probs[b.index][b.cl];
if(diff < 0) return 1;
else if(diff > 0) return -1;
return 0;
}
float overlap(float x1, float w1, float x2, float w2) {
/*
//SLOW METHOD
float l1 = x1 - w1/2;
float l2 = x2 - w2/2;
float left = l1 > l2 ? l1 : l2;
float r1 = x1 + w1/2;
float r2 = x2 + w2/2;
float right = r1 < r2 ? r1 : r2;
return right - left;
*/
//SPALLA METHOD
float l;
w1 < w2? l=w1 : l=w2;
float d = fabs(x1 - x2);
float k = fabs(w1 - w2)/2;
if (d <= k) return l;
else if (d <= k +l) return l - (d-k);
else return 0;
}
float box_intersection(box a, box b) {
float w = overlap(a.x, a.w, b.x, b.w);
if(w <= 0) return 0;
float h = overlap(a.y, a.h, b.y, b.h);
if(h <= 0) return 0;
float area = w*h;
return area;
}
float box_union(box a, box b) {
float i = box_intersection(a, b);
float u = a.w*a.h + b.w*b.h - i;
return u;
}
int max_index(float *a, int n) {
if(n <= 0) return -1;
int i, max_i = 0;
float max = a[0];
for(i = 1; i < n; ++i){
if(a[i] > max){
max = a[i];
max_i = i;
}
}
return max_i;
}
//###############################################################################
float RegionInterpret::box_iou(box a, box b) {
if(fabs(a.x - b.x) > (a.w+b.w)/2 || fabs(a.y - b.y) > (a.h+b.h)/2)
return 0;
return box_intersection(a, b)/box_union(a, b);
}
void RegionInterpret::interpretData(dnnType *data_h, int imageW, int imageH) {
int imW, imH;
if(imageW <= 0 || imageH <= 0) {
imW = input_dim.w;
imH = input_dim.h;
} else {
imW = imageW;
imH = imageH;
}
int tot = output_dim.w*output_dim.h*num;
get_region_boxes(data_h, imW, imH, output_dim.w, output_dim.h, thresh, probs, boxes, 0, 0, 0.5, 1);
//delete repeats
for(int i = 0; i < tot; ++i){
s[i].index = i;
s[i].cl = classes;
s[i].probs = probs;
}
qsort(s, tot, sizeof(sortable_bbox), nms_comparator);
for(int i = 0; i < tot; ++i){
if(probs[s[i].index][classes] == 0) continue;
box a = boxes[s[i].index];
for(int j = i+1; j < tot; ++j){
box b = boxes[s[j].index];
if (box_iou(a, b) > 0.3f){
for(int k = 0; k < classes+1; ++k){
probs[s[j].index][k] = 0;
}
}
}
}
res_boxes_n = 0;
//print results
for(int i = 0; i < tot; ++i){
int cl = max_index(probs[i], classes);
float prob = probs[i][cl];
if(prob > thresh) {
box b = boxes[i];
int x = (b.x)*imW;
int w = (b.w)*imW - b.x;
int y = (b.y)*imH;
int h = (b.h)*imH - b.y;
//if(x < 0) x = 0;
//if(y < 0) y = 0;
//if(w > imW) w = imW;
//if(h > imH) h = imH;
//printf("%d: %.0f%% box(x1, y1, x2, y2): %d %d %d %d\n", cl, prob*100, x, y, w, h);
b.x = x;
b.y = y;
b.h = h;
b.w = w;
b.cl = cl;
b.prob = prob;
res_boxes[res_boxes_n] = b;
res_boxes_n++;
}
}
}
void RegionInterpret::showImageResult(dnnType *input_h) {
#ifdef OPENCV
dataDim_t dim = input_dim;
// read an image
cv::Mat r(dim.h, dim.w, CV_32F, input_h);
cv::Mat g(dim.h, dim.w, CV_32F, input_h + dim.h*dim.w);
cv::Mat b(dim.h, dim.w, CV_32F, input_h + dim.h*dim.w*2);
std::vector<cv::Mat> array_to_merge;
array_to_merge.push_back(b);
array_to_merge.push_back(g);
array_to_merge.push_back(r);
cv::Mat color;
cv::merge(array_to_merge, color);
for(int i=0; i<res_boxes_n; i++) {
box bx = res_boxes[i];
cv::rectangle(color, cv::Point(bx.x - bx.w/2, bx.y - bx.h/2),
cv::Point(bx.x + bx.w/2, bx.y + bx.h/2),
cv::Scalar( 0, 0, 255), 2);
}
cv::namedWindow("result");
// show the image on window
cv::imshow("result", color);
// wait key for 5000 ms
cv::waitKey(0);
#else
std::cout<<"Visualization not supported, please recompile with OpenCV\n";
#endif
}
}}
+34
View File
@@ -0,0 +1,34 @@
#include <iostream>
#include "Layer.h"
#include "kernels.h"
namespace tk { namespace dnn {
Reorg::Reorg(Network *net, int stride) : Layer(net) {
this->stride = stride;
output_dim.n = input_dim.n;
output_dim.c = input_dim.c*stride*stride;
output_dim.h = input_dim.h/stride;
output_dim.w = input_dim.w/stride;
output_dim.l = input_dim.l;
checkCuda( cudaMalloc(&dstData, output_dim.tot()*sizeof(dnnType)) );
}
Reorg::~Reorg() {
checkCuda( cudaFree(dstData) );
}
dnnType* Reorg::infer(dataDim_t &dim, dnnType* srcData) {
reorgForward(srcData, dstData, dim.n, dim.c, dim.h, dim.w, stride);
dim = output_dim;
return dstData;
}
}}
+34
View File
@@ -0,0 +1,34 @@
#include <iostream>
#include "Layer.h"
#include "kernels.h"
namespace tk { namespace dnn {
Reshape::Reshape(Network *net, dataDim_t new_dim) : Layer(net) {
checkCuda( cudaMalloc(&dstData, input_dim.tot()*sizeof(dnnType)) );
output_dim.n = new_dim.n;
output_dim.c = new_dim.c;
output_dim.h = new_dim.h;
output_dim.w = new_dim.w;
output_dim.l = new_dim.l;
}
Reshape::~Reshape() {
checkCuda( cudaFree(dstData) );
}
dnnType* Reshape::infer(dataDim_t &dim, dnnType* srcData) {
//just copies the data and changes the output dim
checkCuda( cudaMemcpy(dstData, srcData, dim.n*dim.c*dim.h*dim.w*sizeof(dnnType), cudaMemcpyDeviceToDevice));
dim = output_dim;
return dstData;
}
}}
+66
View File
@@ -0,0 +1,66 @@
#include <iostream>
#include "Layer.h"
#include "kernels.h"
namespace tk { namespace dnn {
Route::Route(Network *net, Layer **layers, int layers_n, int groups, int group_id) : Layer(net) {
// copy input layers
if(layers_n > MAX_LAYERS) {
FatalError("ROUTE: reached max number of input layers");
}
for(int i=0; i<layers_n; i++) {
this->layers[i] = layers[i];
}
this->layers_n = layers_n;
this->groups = groups;
this->group_id = group_id;
//get dims
output_dim.l = 1;
output_dim.c = 0;
for(int i=0; i<layers_n; i++) {
if(i==0) {
output_dim.w = layers[i]->output_dim.w;
output_dim.h = layers[i]->output_dim.h;
} else {
if( layers[i]->output_dim.w != output_dim.w ||
layers[i]->output_dim.h != output_dim.h )
FatalError("Route Output dim missmatch");
}
output_dim.c += layers[i]->output_dim.c;
}
output_dim.c /= this->groups;
input_dim = output_dim;
checkCuda( cudaMalloc(&dstData, output_dim.tot()*sizeof(dnnType)) );
}
Route::~Route() {
checkCuda( cudaFree(dstData) );
}
dnnType* Route::infer(dataDim_t &dim, dnnType* srcData) {
int offset = 0;
for(int i=0; i<layers_n; i++) {
dnnType *input = layers[i]->dstData;
int in_dim = layers[i]->output_dim.tot();
int part_in_dim = in_dim / this->groups;
checkCuda( cudaMemcpy(dstData + offset, input + this->group_id*part_in_dim, part_in_dim*sizeof(dnnType), cudaMemcpyDeviceToDevice));
offset += part_in_dim;
}
//update data dimensions
dim = output_dim;
return dstData;
}
}}
+37
View File
@@ -0,0 +1,37 @@
#include <iostream>
#include "Layer.h"
#include "kernels.h"
namespace tk { namespace dnn {
Shortcut::Shortcut(Network *net, Layer *backLayer) : Layer(net) {
this->backLayer = backLayer;
checkCuda( cudaMalloc(&dstData, output_dim.tot()*sizeof(dnnType)) );
if( /*backLayer->output_dim.c != input_dim.c ||*/
backLayer->output_dim.w != input_dim.w ||
backLayer->output_dim.h != input_dim.h )
FatalError("Shortcut dim missmatch");
}
Shortcut::~Shortcut() {
checkCuda( cudaFree(dstData) );
}
dnnType* Shortcut::infer(dataDim_t &dim, dnnType* srcData) {
dataDim_t bdim = this->backLayer->output_dim;
checkCuda(cudaMemcpy(dstData, srcData, dim.tot()*sizeof(dnnType), cudaMemcpyDeviceToDevice));
shortcutForward(this->backLayer->dstData, dstData, dim.n, dim.c, dim.h, dim.w, 1, bdim.n, bdim.c, bdim.h, bdim.w, 1);
//update data dimensions
dim = output_dim;
return dstData;
}
}}
+32 -15
View File
@@ -3,25 +3,42 @@
#include "Layer.h"
#include "kernels.h"
namespace tkDNN {
namespace tk { namespace dnn {
Softmax::Softmax(Network *net, dataDim_t input_dim) :
Layer(net, input_dim) {
Softmax::Softmax(Network *net, const tk::dnn::dataDim_t* dim, const cudnnSoftmaxMode_t mode) : Layer(net) {
checkCuda( cudaMalloc(&dstData, input_dim.tot()*sizeof(value_type)) );
checkCuda( cudaMalloc(&dstData, input_dim.tot()*sizeof(dnnType)) );
this->mode = mode;
if(dim == nullptr)
{
this->dim.n= input_dim.n;
this->dim.c= input_dim.c;
this->dim.h= input_dim.h;
this->dim.w= input_dim.w;
this->dim.l= input_dim.l;
}
else
{
this->dim.n= dim->n;
this->dim.c= dim->c;
this->dim.h= dim->h;
this->dim.w= dim->w;
this->dim.l= dim->l;
}
checkCUDNN( cudnnSetTensor4dDescriptor(srcTensorDesc,
net->tensorFormat,
net->dataType,
input_dim.n*input_dim.l,
input_dim.c,
input_dim.h, input_dim.w) );
this->dim.n*this->dim.l,
this->dim.c,
this->dim.h, this->dim.w) );
checkCUDNN( cudnnSetTensor4dDescriptor(dstTensorDesc,
net->tensorFormat,
net->dataType,
input_dim.n*input_dim.l,
input_dim.c,
input_dim.h, input_dim.w) );
this->dim.n*this->dim.l,
this->dim.c,
this->dim.h, this->dim.w) );
}
Softmax::~Softmax() {
@@ -29,13 +46,13 @@ Softmax::~Softmax() {
checkCuda( cudaFree(dstData) );
}
value_type* Softmax::infer(dataDim_t &dim, value_type* srcData) {
dnnType* Softmax::infer(dataDim_t &dim, dnnType* srcData) {
value_type alpha = value_type(1);
value_type beta = value_type(0);
dnnType alpha = dnnType(1);
dnnType beta = dnnType(0);
checkCUDNN( cudnnSoftmaxForward(net->cudnnHandle,
CUDNN_SOFTMAX_ACCURATE ,
CUDNN_SOFTMAX_MODE_CHANNEL,
this->mode,
&alpha,
srcTensorDesc,
srcData,
@@ -45,4 +62,4 @@ value_type* Softmax::infer(dataDim_t &dim, value_type* srcData) {
return dstData;
}
}
}}
+35
View File
@@ -0,0 +1,35 @@
#include <iostream>
#include "Layer.h"
#include "kernels.h"
namespace tk { namespace dnn {
Upsample::Upsample(Network *net, int stride) : Layer(net) {
this->stride = stride;
output_dim.n = input_dim.n;
output_dim.c = input_dim.c;
output_dim.h = input_dim.h*stride;
output_dim.w = input_dim.w*stride;
output_dim.l = input_dim.l;
checkCuda( cudaMalloc(&dstData, output_dim.tot()*sizeof(dnnType)) );
}
Upsample::~Upsample() {
checkCuda( cudaFree(dstData) );
}
dnnType* Upsample::infer(dataDim_t &dim, dnnType* srcData) {
fill(dstData, output_dim.tot(), 0.0);
upsampleForward(srcData, dstData, input_dim.n, input_dim.c, input_dim.h, input_dim.w, stride, 1, 1);
dim = output_dim;
return dstData;
}
}}
+258
View File
@@ -0,0 +1,258 @@
#include <iostream>
#ifdef OPENCV
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#endif
#include "Layer.h"
#include "kernels.h"
namespace tk { namespace dnn {
Yolo::Yolo(Network *net, int classes, int num, std::string fname_weights, int n_masks, float scale_xy) :
Layer(net) {
this->final = true;
this->classes = classes;
this->num = num;
this->n_masks = n_masks;
this->scaleXY = scale_xy;
// load anchors
if(fname_weights != "") {
int seek = 0;
readBinaryFile(fname_weights, n_masks, &mask_h, &mask_d, seek);
seek += n_masks;
readBinaryFile(fname_weights, n_masks*num*2, &bias_h, &bias_d, seek);
//for(int i=0; i<n_masks*num*2; i++)
//printf("%f\n", bias_h[i]);
}
// init default classes name
classesNames.clear();
for(int i=0; i<classes; i++) {
classesNames.push_back(std::to_string(i));
}
// same
output_dim.n = input_dim.n;
output_dim.c = input_dim.c;
output_dim.h = input_dim.h;
output_dim.w = input_dim.w;
output_dim.l = input_dim.l;
checkCuda( cudaMalloc(&dstData, output_dim.tot()*sizeof(dnnType)) );
predictions = nullptr;
}
Yolo::~Yolo() {
checkCuda( cudaFree(dstData) );
}
int entry_index(int batch, int location, int entry,
int classes, dataDim_t &input_dim, dataDim_t &output_dim) {
int n = location / (input_dim.w*input_dim.h);
int loc = location % (input_dim.w*input_dim.h);
return batch*output_dim.tot() + n*input_dim.w*input_dim.h*(4+classes+1) +
entry*input_dim.w*input_dim.h + loc;
}
Yolo::box get_yolo_box(float *x, float *biases, int n, int index, int i, int j, int lw, int lh, int w, int h, int stride) {
Yolo::box b;
b.x = (i + x[index + 0*stride]) / lw;
b.y = (j + x[index + 1*stride]) / lh;
b.w = exp(x[index + 2*stride]) * biases[2*n] / w;
b.h = exp(x[index + 3*stride]) * biases[2*n+1] / h;
return b;
}
dnnType* Yolo::infer(dataDim_t &dim, dnnType* srcData) {
checkCuda( cudaMemcpy(dstData, srcData, dim.tot()*sizeof(dnnType), cudaMemcpyDeviceToDevice));
for (int b = 0; b < dim.n; ++b){
for(int n = 0; n < n_masks; ++n){
int index = entry_index(b, n*dim.w*dim.h, 0, classes, input_dim, output_dim);
activationLOGISTICForward(srcData + index, dstData + index, 2*dim.w*dim.h);
if (this->scaleXY != 1) scalAdd(dstData + index, 2 * dim.w*dim.h, this->scaleXY, -0.5*(this->scaleXY - 1), 1);
index = entry_index(b, n*dim.w*dim.h, 4, classes, input_dim, output_dim);
activationLOGISTICForward(srcData + index, dstData + index, (1+classes)*dim.w*dim.h);
}
}
dim = output_dim;
return dstData;
}
void correct_yolo_boxes(Yolo::detection *dets, int n, int w, int h, int netw, int neth, int relative)
{
int i;
int new_w=0;
int new_h=0;
if (((float)netw/w) < ((float)neth/h)) {
new_w = netw;
new_h = (h * netw)/w;
} else {
new_h = neth;
new_w = (w * neth)/h;
}
for (i = 0; i < n; ++i){
Yolo::box b = dets[i].bbox;
b.x = (b.x - (netw - new_w)/2./netw) / ((float)new_w/netw);
b.y = (b.y - (neth - new_h)/2./neth) / ((float)new_h/neth);
b.w *= (float)netw/new_w;
b.h *= (float)neth/new_h;
if(!relative){
b.x *= w;
b.w *= w;
b.y *= h;
b.h *= h;
}
dets[i].bbox = b;
}
}
int Yolo::computeDetections(Yolo::detection *dets, int &ndets, int netw, int neth, float thresh) {
if(predictions == nullptr)
predictions = new dnnType[output_dim.tot()];
checkCuda( cudaMemcpy(predictions, dstData, output_dim.tot()*sizeof(dnnType), cudaMemcpyDeviceToHost));
int lw = output_dim.w;
int lh = output_dim.h;
if (output_dim.n == 2) {
FatalError("BATCH of 2 not supported");
//avg_flipped_yolo(l);
}
int i,j,n;
int count = ndets;
for (i = 0; i < lw*lh; ++i){
int row = i / lw;
int col = i % lw;
for(n = 0; n < n_masks; ++n){
int obj_index = entry_index(0, n*lw*lh + i, 4, classes, input_dim, output_dim);
float objectness = predictions[obj_index];
if(objectness <= thresh) continue;
int box_index = entry_index(0, n*lw*lh + i, 0, classes, input_dim, output_dim);
dets[count].bbox = get_yolo_box(predictions, bias_h, mask_h[n], box_index, col, row, lw, lh, netw, neth, lw*lh);
dets[count].objectness = objectness;
dets[count].classes = classes;
for(j = 0; j < classes; ++j){
int class_index = entry_index(0, n*lw*lh + i, 4 + 1 + j, classes, input_dim, output_dim);
float prob = objectness*predictions[class_index];
dets[count].prob[j] = (prob > thresh) ? prob : 0;
}
++count;
if(count >= MAX_DETECTIONS)
FatalError("reach max boxes");
}
}
correct_yolo_boxes(dets + ndets, count, netw, neth, netw, neth, 0);
ndets = count;
return count;
}
//////////////////////////////////////////////////////////////////
float yolo_overlap(float x1, float w1, float x2, float w2)
{
float l1 = x1 - w1/2;
float l2 = x2 - w2/2;
float left = l1 > l2 ? l1 : l2;
float r1 = x1 + w1/2;
float r2 = x2 + w2/2;
float right = r1 < r2 ? r1 : r2;
return right - left;
}
float yolo_box_intersection(Yolo::box a, Yolo::box b)
{
float w = yolo_overlap(a.x, a.w, b.x, b.w);
float h = yolo_overlap(a.y, a.h, b.y, b.h);
if(w < 0 || h < 0) return 0;
float area = w*h;
return area;
}
float yolo_box_union(Yolo::box a, Yolo::box b)
{
float i = yolo_box_intersection(a, b);
float u = a.w*a.h + b.w*b.h - i;
return u;
}
float yolo_box_iou(Yolo::box a, Yolo::box b)
{
return yolo_box_intersection(a, b)/yolo_box_union(a, b);
}
int yolo_nms_comparator(const void *pa, const void *pb)
{
Yolo::detection a = *(Yolo::detection *)pa;
Yolo::detection b = *(Yolo::detection *)pb;
float diff = 0;
if(b.sort_class >= 0){
diff = a.prob[b.sort_class] - b.prob[b.sort_class];
} else {
diff = a.objectness - b.objectness;
}
if(diff < 0) return 1;
else if(diff > 0) return -1;
return 0;
}
//////////////////////////////////////////////////////////////////7
Yolo::detection *Yolo::allocateDetections(int nboxes, int classes) {
int i;
Yolo::detection *dets = (Yolo::detection*) calloc(nboxes, sizeof(Yolo::detection));
for(i = 0; i < nboxes; ++i){
dets[i].prob = (float*) calloc(classes, sizeof(float));
}
return dets;
}
void Yolo::mergeDetections(Yolo::detection *dets, int ndets, int classes) {
double nms_thresh = 0.45;
int total = ndets;
int i, j, k;
k = total-1;
for(i = 0; i <= k; ++i){
if(dets[i].objectness == 0){
detection swap = dets[i];
dets[i] = dets[k];
dets[k] = swap;
--k;
--i;
}
}
total = k+1;
for(k = 0; k < classes; ++k){
for(i = 0; i < total; ++i){
dets[i].sort_class = k;
}
qsort(dets, total, sizeof(detection), yolo_nms_comparator);
for(i = 0; i < total; ++i){
if(dets[i].prob[k] == 0) continue;
box a = dets[i].bbox;
for(j = i+1; j < total; ++j){
box b = dets[j].bbox;
if (yolo_box_iou(a, b) > nms_thresh){
dets[j].prob[k] = 0;
}
}
}
}
}
}}
+156
View File
@@ -0,0 +1,156 @@
#include "Yolo3Detection.h"
namespace tk { namespace dnn {
bool Yolo3Detection::init(const std::string& tensor_path, const int n_classes, const int n_batches) {
//convert network to tensorRT
std::cout<<(tensor_path).c_str()<<"\n";
netRT = new tk::dnn::NetworkRT(NULL, (tensor_path).c_str() );
nBatches = n_batches;
tk::dnn::dataDim_t idim = netRT->input_dim;
idim.n = nBatches;
if(netRT->pluginFactory->n_yolos < 2 ) {
FatalError("this is not yolo3");
}
for(int i=0; i<netRT->pluginFactory->n_yolos; i++) {
YoloRT *yRT = netRT->pluginFactory->yolos[i];
classes = yRT->classes;
num = yRT->num;
nMasks = yRT->n_masks;
// make a yolo layer to interpret predictions
yolo[i] = new tk::dnn::Yolo(nullptr, classes, nMasks, ""); // yolo without input and bias
yolo[i]->mask_h = new dnnType[nMasks];
yolo[i]->bias_h = new dnnType[num*nMasks*2];
memcpy(yolo[i]->mask_h, yRT->mask, sizeof(dnnType)*nMasks);
memcpy(yolo[i]->bias_h, yRT->bias, sizeof(dnnType)*num*nMasks*2);
yolo[i]->input_dim = yolo[i]->output_dim = tk::dnn::dataDim_t(1, yRT->c, yRT->h, yRT->w);
yolo[i]->classesNames = yRT->classesNames;
}
dets = tk::dnn::Yolo::allocateDetections(tk::dnn::Yolo::MAX_DETECTIONS, classes);
#ifndef OPENCV_CUDACONTRIB
checkCuda(cudaMallocHost(&input, sizeof(dnnType)*idim.tot()));
#endif
checkCuda(cudaMalloc(&input_d, sizeof(dnnType)*idim.tot()));
// class colors precompute
for(int c=0; c<classes; c++) {
int offset = c*123457 % classes;
float r = getColor(2, offset, classes);
float g = getColor(1, offset, classes);
float b = getColor(0, offset, classes);
colors[c] = cv::Scalar(int(255.0*b), int(255.0*g), int(255.0*r));
}
classesNames = getYoloLayer()->classesNames;
return true;
}
void Yolo3Detection::preprocess(cv::Mat &frame, const int bi){
#ifdef OPENCV_CUDACONTRIB
cv::cuda::GpuMat orig_img, img_resized;
orig_img = cv::cuda::GpuMat(frame);
cv::cuda::resize(orig_img, img_resized, cv::Size(netRT->input_dim.w, netRT->input_dim.h));
img_resized.convertTo(imagePreproc, CV_32FC3, 1/255.0);
//split channels
cv::cuda::split(imagePreproc,bgr);//split source
//write channels
for(int i=0; i<netRT->input_dim.c; i++) {
int size = imagePreproc.rows * imagePreproc.cols;
int ch = netRT->input_dim.c-1 -i;
bgr[ch].download(bgr_h); //TODO: don't copy back on CPU
checkCuda( cudaMemcpy(input_d + i*size + netRT->input_dim.tot()*bi, (float*)bgr_h.data, size*sizeof(dnnType), cudaMemcpyHostToDevice));
}
#else
cv::resize(frame, frame, cv::Size(netRT->input_dim.w, netRT->input_dim.h));
frame.convertTo(imagePreproc, CV_32FC3, 1/255.0);
//split channels
cv::split(imagePreproc,bgr);//split source
//write channels
for(int i=0; i<netRT->input_dim.c; i++) {
int idx = i*imagePreproc.rows*imagePreproc.cols;
int ch = netRT->input_dim.c-1 -i;
memcpy((void*)&input[idx + netRT->input_dim.tot()*bi], (void*)bgr[ch].data, imagePreproc.rows*imagePreproc.cols*sizeof(dnnType));
}
checkCuda(cudaMemcpyAsync(input_d + netRT->input_dim.tot()*bi, input + netRT->input_dim.tot()*bi, netRT->input_dim.tot()*sizeof(dnnType), cudaMemcpyHostToDevice, netRT->stream));
#endif
}
void Yolo3Detection::postprocess(const int bi, const bool mAP){
//get yolo outputs
dnnType *rt_out[netRT->pluginFactory->n_yolos];
for(int i=0; i<netRT->pluginFactory->n_yolos; i++)
rt_out[i] = (dnnType*)netRT->buffersRT[i+1] + netRT->buffersDIM[i+1].tot()*bi;
float x_ratio = float(originalSize[bi].width) / float(netRT->input_dim.w);
float y_ratio = float(originalSize[bi].height) / float(netRT->input_dim.h);
// compute dets
nDets = 0;
for(int i=0; i<netRT->pluginFactory->n_yolos; i++) {
yolo[i]->dstData = rt_out[i];
yolo[i]->computeDetections(dets, nDets, netRT->input_dim.w, netRT->input_dim.h, confThreshold);
}
tk::dnn::Yolo::mergeDetections(dets, nDets, classes);
// fill detected
detected.clear();
for(int j=0; j<nDets; j++) {
tk::dnn::Yolo::box b = dets[j].bbox;
int x0 = (b.x-b.w/2.);
int x1 = (b.x+b.w/2.);
int y0 = (b.y-b.h/2.);
int y1 = (b.y+b.h/2.);
int obj_class = -1;
float prob = 0;
for(int c=0; c<classes; c++) {
if(dets[j].prob[c] >= confThreshold) {
obj_class = c;
prob = dets[j].prob[c];
}
}
if(obj_class >= 0) {
// convert to image coords
x0 = x_ratio*x0;
x1 = x_ratio*x1;
y0 = y_ratio*y0;
y1 = y_ratio*y1;
tk::dnn::box res;
res.cl = obj_class;
res.prob = prob;
res.x = x0;
res.y = y0;
res.w = x1 - x0;
res.h = y1 - y0;
if(mAP)
for(int c=0; c<classes; c++)
res.probs.push_back(dets[j].prob[c]);
detected.push_back(res);
}
}
batchDetected.push_back(detected);
}
tk::dnn::Yolo* Yolo3Detection::getYoloLayer(int n) {
if(n<3)
return yolo[n];
else
return nullptr;
}
}}
+359
View File
@@ -0,0 +1,359 @@
#include "evaluation.h"
#include <fstream>
namespace tk { namespace dnn {
void Frame::print() const{
std::cout<<"labels filename: "<<lFilename<<std::endl;
std::cout<<"image filename: "<<iFilename<<std::endl;
std::cout<<"GT: "<<std::endl;
for(auto g: gt) std::cout<<g;
std::cout<<"DET: "<<std::endl;
for(auto d: det) std::cout<<d;
}
void PR::print(){
std::cout<<"precision: "<<precision<<" recall: "<<recall<<" tp: "<<tp<<" fp:"<<fp<<" fn:"<<fn<<std::endl;
}
void readmAPParams( const char* config_filename, int& classes, int& map_points,
int& map_levels, float& map_step, float& IoU_thresh,
float& conf_thresh, bool& verbose) {
YAML::Node config = YAML::LoadFile(config_filename);
classes = config["classes"].as<int>();
map_points = config["map_points"].as<int>();
map_levels = config["map_levels"].as<int>();
map_step = config["map_step"].as<float>();
IoU_thresh = config["IoU_thresh"].as<float>();
conf_thresh = config["conf_thresh"].as<float>();
verbose = config["verbose"].as<bool>();
}
/* Credits to https://github.com/AlexeyAB/darknet/blob/master/src/detector.c*/
double computeMap( std::vector<Frame> &images,const int classes,
const float IoU_thresh, const float conf_thresh,
const int map_points, const bool verbose) {
if(verbose)
for(auto img:images)
img.print();
int detections_count = 0;
int groundtruths_count = 0;
int unique_truth_count = 0;
std::vector<int> truth_classes_count(classes,0);
std::vector<int> dets_classes_count(classes,0);
//count groundtruth and detections in total and for each class
for(auto i:images){
for(auto gt:i.gt)
truth_classes_count[gt.cl]++;
for(auto det:i.det)
dets_classes_count[det.cl]++;
detections_count += i.det.size();
groundtruths_count += i.gt.size();
}
if(verbose){
std::cout<<"gt_count: "<<groundtruths_count<<std::endl;
std::cout<<"det_count: "<<detections_count<<std::endl;
}
std::vector<BoundingBox> all_dets;
std::vector<BoundingBox> all_gts;
int gt_checked = 0;
// for each detection comput IoU with groundtruth and match detetcion and
// groundtruth with IoU greater than IoU_thresh
for(auto &img:images){
for(size_t i=0; i<img.det.size(); i++){
if(img.det[i].prob > conf_thresh){
float maxIoU = 0;
int truth_index = -1;
for(size_t j=0; j<img.gt.size(); j++){
float currentIoU = img.det[i].IoU(img.gt[j]);
if(currentIoU > maxIoU && img.det[i].cl == img.gt[j].cl){
maxIoU = currentIoU;
truth_index = j;
}
}
if(truth_index > -1 && maxIoU > IoU_thresh){
img.det[i].uniqueTruthIndex = truth_index + gt_checked;
img.det[i].truthFlag = 1;
img.det[i].maxIoU = maxIoU;
}
}
all_dets.push_back(img.det[i]);
}
gt_checked += img.gt.size();
}
if(verbose){
for(auto img:images)
img.print();
std::cout<<"\n\n\n\n";
}
//sort all detections by descending value of confidence
std::sort(all_dets.begin(), all_dets.end(), boxComparison);
std::vector<int> truth_flags(groundtruths_count,0);
if(verbose)
for(auto d:all_dets)
std::cout<<d;
//compute precision-recall curve
std::vector<std::vector<PR>> pr( classes, std::vector<PR>(detections_count));
for(int rank = 0; rank< detections_count; ++rank){
if (rank > 0) {
for (int class_id = 0; class_id < classes; ++class_id) {
pr[class_id][rank].tp = pr[class_id][rank - 1].tp;
pr[class_id][rank].fp = pr[class_id][rank - 1].fp;
}
}
//if it was detected and never detected before
if (all_dets[rank].truthFlag == 1 && truth_flags[all_dets[rank].uniqueTruthIndex] == 0) {
truth_flags[all_dets[rank].uniqueTruthIndex] = 1;
pr[all_dets[rank].cl][rank].tp++; // true-positive
}
else {
pr[all_dets[rank].cl][rank].fp++; // false-positive
}
for (int i = 0; i < classes; ++i){
const int tp = pr[i][rank].tp;
const int fp = pr[i][rank].fp;
const int fn = truth_classes_count[i] - tp; // false-negative = objects - true-positive
pr[i][rank].fn = fn;
if ((tp + fp) > 0)
pr[i][rank].precision = (double)tp / (double)(tp + fp);
else
pr[i][rank].precision = 0;
if ((tp + fn) > 0)
pr[i][rank].recall = (double)tp / (double)(tp + fn);
else
pr[i][rank].recall = 0;
if (rank == (detections_count - 1) && dets_classes_count[i] != (tp + fp)) {
// check for last rank
printf(" class_id: %d - detections = %d, tp+fp = %d, tp = %d, fp = %d \n", i, dets_classes_count[i], tp+fp, tp, fp);
}
}
}
if(verbose){
for(int i=0; i < pr.size(); i++) {
std::cout<<"---------Class "<<i<<std::endl;
for(auto r:pr[i])
r.print();
}
}
//compute average precision for each class. Two methods are avaible,
//based on map_points required
double mean_average_precision = 0;
double last_recall, last_precision, delta_recall;
double cur_recall, cur_precision;
double avg_precision = 0;
for (int i = 0; i < classes; ++i) {
avg_precision = 0;
if (map_points == 0){ //mAP calculation: ImageNet, PascalVOC 2010-2012
last_recall = pr[i][detections_count - 1].recall;
last_precision = pr[i][detections_count - 1].precision;
for (int rank = detections_count - 2; rank >= 0; --rank){
delta_recall = last_recall - pr[i][rank].recall;
last_recall = pr[i][rank].recall;
if (pr[i][rank].precision > last_precision)
last_precision = pr[i][rank].precision;
avg_precision += delta_recall * last_precision;
}
}
else {//MSCOCO - 101 Recall-points, PascalVOC - 11 Recall-points
for (int point = 0; point < map_points; ++point) {
cur_recall = point * 1.0 / ( map_points - 1 );
cur_precision = 0;
for (int rank = 0; rank < detections_count; ++rank)
if (pr[i][rank].recall >= cur_recall && pr[i][rank].precision > cur_precision)
cur_precision = pr[i][rank].precision;
avg_precision += cur_precision;
}
avg_precision = avg_precision / map_points;
}
if(verbose)
std::cout<<"Class: "<<i<<" AP: "<< avg_precision<<std::endl;
mean_average_precision += avg_precision;
}
mean_average_precision = mean_average_precision / classes;
std::cout<<"Classes: "<<classes<<" mAP " <<IoU_thresh<<":\t"<< mean_average_precision<<std::endl;
return mean_average_precision;
}
double computeMapNIoULevels(std::vector<Frame> &images,const int classes,
const float i_IoU_thresh, const float conf_thresh,
const int map_points, const float map_step,
const int map_levels, const bool verbose,
const bool write_on_file, std::string net) {
std::ofstream out_file;
if(write_on_file){
out_file.open("map.csv", std::ios_base::app);
out_file<<net<<";";
}
double AP = 0, cur_AP = 0;
float IoU_thresh = i_IoU_thresh;
for(int i=0; i<map_levels; ++i){
//clear detection-grounthuth matching
for(auto& img:images)
for(auto & d:img.det)
d.clear();
//compute mAP for the new IoU threshold
cur_AP = computeMap(images,classes,IoU_thresh,conf_thresh,map_points, verbose);
if(write_on_file)
out_file<<cur_AP<<";";
AP += cur_AP;
IoU_thresh +=map_step;
}
AP/=map_levels;
if(write_on_file){
out_file<<AP<<"\n";
out_file.close();
}
return AP;
}
void computeTPFPFN( std::vector<Frame> &images,const int classes,
const float IoU_thresh, const float conf_thresh,
bool verbose, const bool write_on_file, std::string net) {
std::ofstream out_file;
if(write_on_file){
out_file.open("pr.csv", std::ios_base::app);
out_file<<net<<";";
}
std::vector<int> truth_classes_count(classes,0);
std::vector<int> dets_classes_count(classes,0);
std::vector<PR> pr(classes);
//compute TP, FP, FN for each image, for each class
for(auto &img:images){
for(auto& tc: truth_classes_count) tc = 0;
for(auto& dc: dets_classes_count) dc = 0;
std::vector<bool> det_assigned(img.det.size(), false);
for(size_t j=0; j<img.gt.size(); j++){
truth_classes_count[img.gt[j].cl]++;
float maxIoU = 0;
int det_index = -1;
for(size_t i=0; i<img.det.size(); i++){
if(img.det[i].prob > conf_thresh){
float currentIoU = img.det[i].IoU(img.gt[j]);
if(currentIoU > maxIoU && img.det[i].cl == img.gt[j].cl && !det_assigned[i]){
maxIoU = currentIoU;
det_index = i;
}
}
}
if(det_index > -1 && maxIoU > IoU_thresh && !det_assigned[det_index]){
img.det[det_index].uniqueTruthIndex = j;
img.det[det_index].truthFlag = 1;
img.det[det_index].maxIoU = maxIoU;
det_assigned[det_index] = true;
dets_classes_count[img.det[det_index].cl]++;
}
}
for(size_t i=0; i<img.det.size(); i++){
if(img.det[i].truthFlag)
pr[img.det[i].cl].tp ++;
else
pr[img.det[i].cl].fp ++;
}
for(size_t i=0; i<classes; i++){
pr[i].fn += truth_classes_count[i] - dets_classes_count[i];
}
}
//count all TP, FP, FN and compute precsion, recall and f1-score
double avg_precision = 0, avg_recall = 0, f1_score = 0;
int TP = 0, FP = 0, FN = 0;
for(size_t i=0; i<classes; i++){
pr[i].precision = (pr[i].tp + pr[i].fp) > 0 ? (double)pr[i].tp / (double)(pr[i].tp +pr[i].fp) : 0;
pr[i].recall = (pr[i].tp + pr[i].fn) > 0 ? (double)pr[i].tp / (double)(pr[i].tp +pr[i].fn) : 0;
if(verbose)
std::cout<<"Class "<<i<<"\tTP: "<<pr[i].tp<<"\tFP: "<<pr[i].fp<<"\tFN: "<<pr[i].fn<<"\tprecision: "<<pr[i].precision<<"\trecall: "<<pr[i].recall<<std::endl;
avg_precision += pr[i].precision;
avg_recall += pr[i].recall;
TP += pr[i].tp;
FP += pr[i].fp;
FN += pr[i].fn;
}
avg_precision /= classes;
avg_recall /= classes;
f1_score = avg_precision + avg_recall > 0 ? 2 * ( avg_precision * avg_recall ) / ( avg_precision + avg_recall ) : 0;
if(write_on_file){
out_file<<TP<<";"<<FP<<";"<<FN<<";"<<avg_precision<<";"<<avg_recall<<";"<<f1_score<<"\n";
out_file.close();
}
std::cout<<"avg precision: "<<avg_precision<<"\tavg recall: "<<avg_recall<<"\tavg f1 score:"<<f1_score<<std::endl;
}
void printJsonCOCOFormat(std::ofstream *out_file, const std::string image_path, std::vector<tk::dnn::box> bbox, const int classes, const int w, const int h)
{
int coco_ids[] = { 1,2,3,4,5,6,7,8,9,10,11,13,14,15,16,17,18,19,20,21,22,23,24,25,27,28,31,32,33,34,35,36,37,38,39,40,41,42,43,44,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,67,70,72,73,74,75,76,77,78,79,80,81,82,84,85,86,87,88,89,90 };
std::string id = image_path.substr(image_path.find("images/")+7, image_path.find(".jpg") - image_path.find("images/") -7);
int image_id = std::stoi(id);
for (int i = 0; i < bbox.size(); ++i) {
float xmin = bbox[i].x ;
float xmax = bbox[i].x + float(bbox[i].w);
float ymin = bbox[i].y;
float ymax = bbox[i].y + float(bbox[i].h);
//limit to image borders
if (xmin < 0) xmin = 0;
if (ymin < 0) ymin = 0;
if (xmax > w) xmax = w;
if (ymax > h) ymax = h;
float bx = xmin;
float by = ymin;
float bw = xmax - xmin;
float bh = ymax - ymin;
if(bbox[i].probs.size() == classes)
for (int j = 0; j < classes; ++j) {
//min threshold confidence is set in DetectionNN.h
if (bbox[i].probs[j] > 0) {
*out_file << "{\"image_id\":" << image_id <<
", \"category_id\":" << coco_ids[j] <<
", \"bbox\":[" << bx << ", " << by << ", " << bw << ", " << bh <<
"], \"score\":" << bbox[i].probs[j] << "},\n";
}
}
else
*out_file << "{\"image_id\":" << image_id <<
", \"category_id\":" << coco_ids[bbox[i].cl] <<
", \"bbox\":[" << bx << ", " << by << ", " << bw << ", " << bh <<
"], \"score\":" << bbox[i].prob << "},\n";
}
}
}}
+5 -6
View File
@@ -7,12 +7,12 @@
x > 0 : y = x
*/
__global__
void activation_elu(value_type *input, value_type *output, int size) {
void activation_elu(dnnType *input, dnnType *output, int size) {
int i = blockDim.x*blockIdx.x + threadIdx.x;
if(i<size) {
value_type k0, k1;
dnnType k0, k1;
if (input[i]>0)
k0 = 1.0f;
@@ -28,11 +28,10 @@ void activation_elu(value_type *input, value_type *output, int size) {
/**
ELU activation function
*/
void activationELUForward(value_type* srcData, value_type* dstData, int size)
void activationELUForward(dnnType* srcData, dnnType* dstData, int size, const cudaStream_t stream)
{
int blocks = (size+255)/256;
int threads = 256;
activation_elu<<<blocks, threads>>>(srcData, dstData, size);
checkCuda( cudaDeviceSynchronize() );
}
activation_elu<<<blocks, threads, 0, stream>>>(srcData, dstData, size);
}
+28
View File
@@ -0,0 +1,28 @@
#include "kernels.h"
__global__
void activation_leaky(dnnType *input, dnnType *output, int size) {
int i = blockDim.x*blockIdx.x + threadIdx.x;
if(i<size) {
if (input[i]>0)
output[i] = input[i];
else
output[i] = 0.1f*input[i];
}
}
/**
ELU activation function
*/
void activationLEAKYForward(dnnType* srcData, dnnType* dstData, int size, cudaStream_t stream)
{
int blocks = (size+255)/256;
int threads = 256;
activation_leaky<<<blocks, threads, 0, stream>>>(srcData, dstData, size);
}
+25
View File
@@ -0,0 +1,25 @@
#include "kernels.h"
__global__
void activation_logistic(dnnType *input, dnnType *output, int size) {
int i = blockDim.x*blockIdx.x + threadIdx.x;
if(i<size) {
output[i] = 1.0f/(1.0f + exp(-input[i]));;
}
}
/**
LOGISTIC activation function
*/
void activationLOGISTICForward(dnnType* srcData, dnnType* dstData, int size, cudaStream_t stream)
{
int blocks = (size+255)/256;
int threads = 256;
activation_logistic<<<blocks, threads, 0, stream>>>(srcData, dstData, size);
}
+50
View File
@@ -0,0 +1,50 @@
#include "kernels.h"
#include <math.h>
#define MISH_THRESHOLD 20
__device__
float tanh_activate_kernel(float x){return (2/(1 + expf(-2*x)) - 1);}
__device__
float softplus_kernel(float x, float threshold = 20) {
if (x > threshold) return x; // too large
else if (x < -threshold) return expf(x); // too small
return logf(expf(x) + 1);
}
__device__
float mish_yashas(float x) {
float e = __expf(x);
if (x <= -18.0f)
return x * e;
float n = e * e + 2 * e;
if (x <= -5.0f)
return x * __fdividef(n, n + 2);
return x - 2 * __fdividef(x, n + 2);
}
// https://github.com/digantamisra98/Mish
// https://github.com/AlexeyAB/darknet/blob/master/src/activation_kernels.cu
__global__
void activation_mish(dnnType *input, dnnType *output, int size) {
int i = (blockIdx.x + blockIdx.y*gridDim.x) * blockDim.x + threadIdx.x;
if (i < size)
// output[i] = input[i] * tanh_activate_kernel( softplus_kernel(input[i], MISH_THRESHOLD));
output[i] = mish_yashas(input[i]);
}
/**
Mish activation function
*/
void activationMishForward(dnnType* srcData, dnnType* dstData, int size, cudaStream_t stream)
{
int blocks = (size+255)/256;
int threads = 256;
activation_mish<<<blocks, threads, 0, stream>>>(srcData, dstData, size);
}
+33
View File
@@ -0,0 +1,33 @@
#include "kernels.h"
__global__
void activation_relu_ceiling(dnnType *input, dnnType *output, int size, const float ceiling) {
int i = blockDim.x*blockIdx.x + threadIdx.x;
if(i<size) {
if (input[i]>0)
{
if (input[i]>ceiling)
output[i] = ceiling;
else
output[i] = input[i];
}
else
output[i] = 0.0f;
}
}
/**
Relu ceiling activation function
*/
void activationReLUCeilingForward(dnnType* srcData, dnnType* dstData, int size, const float ceiling, cudaStream_t stream)
{
int blocks = (size+255)/256;
int threads = 256;
activation_relu_ceiling<<<blocks, threads, 0, stream>>>(srcData, dstData, size, ceiling);
}
+23
View File
@@ -0,0 +1,23 @@
#include "kernels.h"
#include <math.h>
__global__
void activation_sigmoid(dnnType *input, dnnType *output, int size) {
int i = blockDim.x * blockIdx.x + threadIdx.x;
if(i < size)
output[i] = 1.0f / (1.0f + exp (-input[i]));
}
/**
ELU activation function
*/
void activationSIGMOIDForward(dnnType* srcData, dnnType* dstData, int size, cudaStream_t stream)
{
int blocks = (size+255)/256;
int threads = 256;
activation_sigmoid<<<blocks, threads, 0, stream>>>(srcData, dstData, size);
}
+21
View File
@@ -0,0 +1,21 @@
#include "kernels.h"
__global__
void float2half_device(float *input, __half *output, int size) {
int i = blockDim.x*blockIdx.x + threadIdx.x;
if(i<size) {
output[i] = __float2half(input[i]);
}
}
void float2half(float* srcData, __half *dstData, int size, const cudaStream_t stream)
{
int blocks = (size+255)/256;
int threads = 256;
float2half_device<<<blocks, threads, 0, stream>>>(srcData, dstData, size);
cudaDeviceSynchronize();
}
+300
View File
@@ -0,0 +1,300 @@
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
#include <iostream>
#include "kernels.h"
#include <errno.h>
#define CUDA_KERNEL_LOOP(i, n) \
for (int i = blockIdx.x * blockDim.x + threadIdx.x; \
i < (n); \
i += blockDim.x * gridDim.x)
const int CUDA_NUM_THREADS = 512;
inline int GET_BLOCKS(const int N)
{
return (N + CUDA_NUM_THREADS - 1) / CUDA_NUM_THREADS;
}
__device__ float dmcn_im2col_bilinear(const float *bottom_data, const int data_width,
const int height, const int width, float h, float w) {
int h_low = floor(h);
int w_low = floor(w);
int h_high = h_low + 1;
int w_high = w_low + 1;
float lh = h - h_low;
float lw = w - w_low;
float hh = 1 - lh, hw = 1 - lw;
float v1 = ( (h_low >= 0 && w_low >= 0) ? bottom_data[h_low * data_width + w_low]:0);
float v2 = ( (h_low >= 0 && w_high <= width - 1) ? bottom_data[h_low * data_width + w_high]:0);
float v3 = ( (h_high <= height - 1 && w_low >= 0) ? bottom_data[h_high * data_width + w_low]:0);
float v4 = ( (h_high <= height - 1 && w_high <= width - 1) ? bottom_data[h_high * data_width + w_high]:0);
float w1 = hh * hw, w2 = hh * lw, w3 = lh * hw, w4 = lh * lw;
float val = (w1 * v1 + w2 * v2 + w3 * v3 + w4 * v4);
return val;
}
__global__ void modulated_deformable_im2col_gpu_kernel(const int n,
const float *data_im, const float *data_offset, const float *data_mask,
const int height, const int width,
const int batch_size, const int num_channels, const int deformable_group,
const int height_col, const int width_col,
float *data_col) {
CUDA_KERNEL_LOOP(index, n)
{
//If n is a power of 2, ( i / n ) is equivalent to ( i ≫ log2 n ) and ( i % n ) is equivalent to ( i & n - 1 ).
const int ind_on_w = index / width_col;
const int ind_on_w_on_h = ind_on_w / height_col;
const int kk = 3 * 3;
// index index of output matrix
const int w_col = index % width_col;
const int h_col = (ind_on_w) % height_col;
const int b_col = (ind_on_w_on_h) % batch_size;
const int c_im = (ind_on_w_on_h) / batch_size;
const int c_col = c_im * kk;
// compute deformable group index
const int deformable_group_index = c_im / (int)(num_channels / deformable_group);
const int h_in = h_col - 1;
const int w_in = w_col - 1;
const int s_col = height_col * width_col;
const int s_col2 = 2 * s_col;
const int first_member = w_col + width_col * h_col;
// float *data_col_ptr = data_col + ((c_col * batch_size + b_col) * height_col + h_col) * width_col + w_col;
float *data_col_ptr = data_col + first_member + s_col * (c_col * batch_size + b_col);
//const float* data_im_ptr = data_im + ((b_col * num_channels + c_im) * height + h_in) * width + w_in;
const float *data_im_ptr = data_im + (b_col * num_channels + c_im) * height * width;
const int add_ptr = (b_col * deformable_group + deformable_group_index) * kk * s_col;
const float *data_offset_ptr = data_offset + add_ptr + add_ptr;
const float *data_mask_ptr = data_mask + add_ptr;
#pragma unroll
for (int i = 0; i < 3; ++i) {
#pragma unroll
for (int j = 0; j < 3; ++j) {
const int iter_member = (i * 3 + j);
// const int data_offset_h_ptr = ((2 * (i * kernel_w + j)) * height_col + h_col) * width_col + w_col;
const int data_offset_h_ptr = first_member + s_col2 * iter_member;
// const int data_offset_w_ptr = ((2 * (i * kernel_w + j) + 1) * height_col + h_col) * width_col + w_col;
const int data_offset_w_ptr = s_col + first_member + s_col2 * iter_member;
// const int data_mask_hw_ptr = ((i * kernel_w + j) * height_col + h_col) * width_col + w_col;
const int data_mask_hw_ptr = first_member + s_col * iter_member;
const float offset_h = data_offset_ptr[data_offset_h_ptr];
const float offset_w = data_offset_ptr[data_offset_w_ptr];
const float mask = data_mask_ptr[data_mask_hw_ptr];
const float h_im = offset_h + h_in + i;
const float w_im = offset_w + w_in + j;
//if (h_im >= 0 && w_im >= 0 && h_im < height && w_im < width) {
float val = static_cast<float>(0);
if (h_im < height && w_im < width && h_im > -1 && w_im > -1) {
//const float map_h = i * dilation_h + offset_h;
//const float map_w = j * dilation_w + offset_w;
//const int cur_height = height - h_in;
//const int cur_width = width - w_in;
//val = dmcn_im2col_bilinear(data_im_ptr, width, cur_height, cur_width, map_h, map_w);
val = dmcn_im2col_bilinear(data_im_ptr, width, height, width, h_im, w_im);
}
*data_col_ptr = val * mask;
data_col_ptr += batch_size * s_col;
//data_col_ptr += height_col * width_col;
}
}
}
}
__global__ void modulated_deformable_im2col_gpu_kernel_general_version(const int n,
const float *data_im, const float *data_offset, const float *data_mask,
const int height, const int width, const int kernel_h, const int kernel_w,
const int pad_h, const int pad_w,
const int stride_h, const int stride_w,
const int dilation_h, const int dilation_w,
const int channel_per_deformable_group,
const int batch_size, const int num_channels, const int deformable_group,
const int height_col, const int width_col,
float *data_col) {
CUDA_KERNEL_LOOP(index, n)
{
//If n is a power of 2, ( i / n ) is equivalent to ( i ≫ log2 n ) and ( i % n ) is equivalent to ( i & n - 1 ).
const int ind_on_w = index / width_col;
const int ind_on_w_on_h = ind_on_w / height_col;
const int kk = kernel_h * kernel_w;
// index index of output matrix
const int w_col = index % width_col;
const int h_col = (ind_on_w) % height_col;
const int b_col = (ind_on_w_on_h) % batch_size;
const int c_im = (ind_on_w_on_h) / batch_size;
const int c_col = c_im * kk;
// compute deformable group index
const int deformable_group_index = c_im / channel_per_deformable_group;
const int h_in = h_col * stride_h - pad_h;
const int w_in = w_col * stride_w - pad_w;
const int s_col = height_col * width_col;
const int s_col2 = 2 * s_col;
const int first_member = w_col + width_col * h_col;
// float *data_col_ptr = data_col + ((c_col * batch_size + b_col) * height_col + h_col) * width_col + w_col;
float *data_col_ptr = data_col + first_member + s_col * (c_col * batch_size + b_col);
//const float* data_im_ptr = data_im + ((b_col * num_channels + c_im) * height + h_in) * width + w_in;
const float *data_im_ptr = data_im + (b_col * num_channels + c_im) * height * width;
const int add_ptr = (b_col * deformable_group + deformable_group_index) * kk * s_col;
const float *data_offset_ptr = data_offset + add_ptr + add_ptr;
const float *data_mask_ptr = data_mask + add_ptr;
#pragma unroll
for (int i = 0; i < kernel_h; ++i) {
#pragma unroll
for (int j = 0; j < kernel_w; ++j) {
const int iter_member = (i * kernel_w + j);
// const int data_offset_h_ptr = ((2 * (i * kernel_w + j)) * height_col + h_col) * width_col + w_col;
const int data_offset_h_ptr = first_member + s_col2 * iter_member;
// const int data_offset_w_ptr = ((2 * (i * kernel_w + j) + 1) * height_col + h_col) * width_col + w_col;
const int data_offset_w_ptr = s_col + first_member + s_col2 * iter_member;
// const int data_mask_hw_ptr = ((i * kernel_w + j) * height_col + h_col) * width_col + w_col;
const int data_mask_hw_ptr = first_member + s_col * iter_member;
const float offset_h = data_offset_ptr[data_offset_h_ptr];
const float offset_w = data_offset_ptr[data_offset_w_ptr];
const float mask = data_mask_ptr[data_mask_hw_ptr];
const float h_im = offset_h + h_in + i * dilation_h;
const float w_im = offset_w + w_in + j * dilation_w;
//if (h_im >= 0 && w_im >= 0 && h_im < height && w_im < width) {
float val = static_cast<float>(0);
if (h_im < height && w_im < width && h_im > -1 && w_im > -1) {
//const float map_h = i * dilation_h + offset_h;
//const float map_w = j * dilation_w + offset_w;
//const int cur_height = height - h_in;
//const int cur_width = width - w_in;
//val = dmcn_im2col_bilinear(data_im_ptr, width, cur_height, cur_width, map_h, map_w);
val = dmcn_im2col_bilinear(data_im_ptr, width, height, width, h_im, w_im);
}
*data_col_ptr = val * mask;
data_col_ptr += batch_size * s_col;
//data_col_ptr += height_col * width_col;
}
}
}
}
void modulatedDeformableIm2colCuda(cudaStream_t stream,
const float* data_im, const float* data_offset, const float* data_mask,
const int batch_size, const int channels, const int height_im, const int width_im,
const int height_col, const int width_col,
const int deformable_group, float* data_col) {
// num_axes should be smaller than block size
// const int channel_per_deformable_group = channels / deformable_group;
const int num_kernels = channels * batch_size * height_col * width_col;
modulated_deformable_im2col_gpu_kernel
<<<GET_BLOCKS(num_kernels), CUDA_NUM_THREADS,
0, stream>>>(
num_kernels, data_im, data_offset, data_mask, height_im, width_im,
batch_size, channels, deformable_group, height_col, width_col, data_col);
cudaError_t err = cudaGetLastError();
if (err != cudaSuccess)
FatalError("error in modulatedDeformableIm2colCuda: " + std::string(cudaGetErrorString(err)) + "\n");
}
void modulatedDeformableIm2colCudaGeneralVersion(cudaStream_t stream,
const float* data_im, const float* data_offset, const float* data_mask,
const int batch_size, const int channels, const int height_im, const int width_im,
const int height_col, const int width_col, const int kernel_h, const int kenerl_w,
const int pad_h, const int pad_w, const int stride_h, const int stride_w,
const int dilation_h, const int dilation_w,
const int deformable_group, float* data_col) {
// num_axes should be smaller than block size
const int channel_per_deformable_group = channels / deformable_group;
const int num_kernels = channels * batch_size * height_col * width_col;
modulated_deformable_im2col_gpu_kernel_general_version
<<<GET_BLOCKS(num_kernels), CUDA_NUM_THREADS,
0, stream>>>(
num_kernels, data_im, data_offset, data_mask, height_im, width_im, kernel_h, kenerl_w,
pad_h, pad_w, stride_h, stride_w, dilation_h, dilation_w, channel_per_deformable_group,
batch_size, channels, deformable_group, height_col, width_col, data_col);
cudaError_t err = cudaGetLastError();
if (err != cudaSuccess)
FatalError("error in modulatedDeformableIm2colCudaGeneralVersion: " + std::string(cudaGetErrorString(err)) + "\n");
}
void dcnV2CudaForward(cublasStatus_t stat, cublasHandle_t handle,
float *input, float *weight,
float *bias, float *ones,
float *offset, float *mask,
float *output, float *columns,
int kernel_h, int kernel_w,
const int stride_h, const int stride_w,
const int pad_h, const int pad_w,
const int dilation_h, const int dilation_w,
const int deformable_group, const int batch_id,
const int in_n, const int in_c, const int in_h, const int in_w,
const int out_n, const int out_c, const int out_h, const int out_w,
const int chunk_dim, cudaStream_t stream)
{
// stat and handle have be moved out to preserve 2 - 6 milliseconds every 100.
const int batch = batch_id;
const int channels = in_c;
const int height = in_h;
const int width = in_w;
const int channels_out = out_c;
const int height_out = (height + 2 * pad_h - (dilation_h * (kernel_h - 1) + 1)) / stride_h + 1;
const int width_out = (width + 2 * pad_w - (dilation_w * (kernel_w - 1) + 1)) / stride_w + 1;
long m = channels_out;
long n = height_out * width_out;
long k = 1;
float alpha = 1.0;
float beta = 0.0;
stat = cublasSgemm(handle, CUBLAS_OP_T, CUBLAS_OP_N,
n, m, k, &alpha,
ones, k, bias, k,
&beta, output + batch * out_c * out_h * out_w, n);
if (stat != CUBLAS_STATUS_SUCCESS)
FatalError("CUBLAS initialization failed\n");
modulatedDeformableIm2colCuda(stream,
input + batch * channels * height * width,
offset,// + b * 2 * int((float)chunk_dim / batch),
mask,// + b * int((float)chunk_dim / batch),
1, channels, height, width,
height_out, width_out, deformable_group, columns);
// modulatedDeformableIm2colCudaGeneralVersion(stream,
// input, offset,
// mask,
// 1, channels, height, width,
// height_out, width_out, kernel_h, kernel_w,
// pad_h, pad_w, stride_h, stride_w, dilation_h, dilation_w,
// deformable_group, columns);
//(k * m) x (m * n)
// Y = WC
k = channels * kernel_h * kernel_w;
beta = 1.0;
stat = cublasSgemm(handle, CUBLAS_OP_N, CUBLAS_OP_N,
n, m, k, &alpha,
columns, n, weight, k,
&beta, output + batch * out_c * out_h * out_w, n);
if (stat != CUBLAS_STATUS_SUCCESS)
FatalError("CUBLAS initialization failed\n");
}
+21
View File
@@ -0,0 +1,21 @@
#include "kernels.h"
__global__
void fill_kernel(dnnType *data, int size, dnnType val) {
int i = blockDim.x*blockIdx.x + threadIdx.x;
if(i<size) {
data[i] = val;
}
}
void fill(dnnType* data, int size, dnnType val, cudaStream_t stream)
{
int blocks = (size+255)/256;
int threads = 256;
fill_kernel<<<blocks, threads, 0, stream>>>(data, size, val);
}
+16
View File
@@ -0,0 +1,16 @@
#include "kernelsThrust.h"
__global__
void normalize_kernel(float *bgr, const int dim, const float *mean, const float *stddev){
int i = blockDim.x*blockIdx.x + threadIdx.x;
int j = blockIdx.y;
bgr[j*(dim)+i] = bgr[j*(dim)+i] - mean[j];
bgr[j*(dim)+i] = bgr[j*(dim)+i] / stddev[j];
}
void normalize(float *bgr, const int ch, const int h, const int w, const float *mean, const float *stddev){
int num_thread = 256;
dim3 dimBlock(h*w/num_thread, ch);
normalize_kernel<<<dimBlock, num_thread, 0>>>(bgr, h*w, mean, stddev);
}
+52
View File
@@ -0,0 +1,52 @@
#include "kernels.h"
__global__ void forward_maxpool_layer_kernel(int n, int in_h, int in_w, int in_c, int stride_x, int stride_y, int size, int pad, float *input, float *output)
{
int h = (in_h + pad - size) / stride_y + 1;
int w = (in_w + pad - size) / stride_x + 1;
int c = in_c;
int id = (blockIdx.x + blockIdx.y*gridDim.x) * blockDim.x + threadIdx.x;
if(id >= n) return;
int j = id % w;
id /= w;
int i = id % h;
id /= h;
int k = id % c;
id /= c;
int b = id;
int w_offset = -pad / 2;
int h_offset = -pad / 2;
int out_index = j + w*(i + h*(k + c*b));
float max = -9999999;
int max_i = -1;
int l, m;
for(l = 0; l < size; ++l){
for(m = 0; m < size; ++m){
int cur_h = h_offset + i*stride_y + l;
int cur_w = w_offset + j*stride_x + m;
int index = cur_w + in_w*(cur_h + in_h*(k + b*in_c));
int valid = (cur_h >= 0 && cur_h < in_h &&
cur_w >= 0 && cur_w < in_w);
float val = (valid != 0) ? input[index] : -9999999;
max_i = (val > max) ? index : max_i;
max = (val > max) ? val : max;
}
}
output[out_index] = max;
}
void MaxPoolingForward(dnnType* srcData, dnnType* dstData, int n, int c, int h, int w, int stride_x, int stride_y, int size, int padding, cudaStream_t stream)
{
int tot_size = n*c*h*w;
int blocks = (tot_size+255)/256;
int threads = 256;
forward_maxpool_layer_kernel<<<blocks, threads, 0, stream>>>(tot_size, h, w, c, stride_x, stride_y, size, padding, srcData, dstData);
}
+71
View File
@@ -0,0 +1,71 @@
#include "kernelsThrust.h"
void subtractWithThreshold(dnnType *src_begin, dnnType *src_end, dnnType *src2_begin, dnnType *src_out, struct threshold op){
thrust::transform(thrust::device, src_begin, src_end, src2_begin, src_out, op);
}
void sort(dnnType *src_begin, dnnType *src_end, int *idsrc){
thrust::sort_by_key(thrust::device,
src_begin, src_end, idsrc,
thrust::greater<float>());
// thrust::stable_sort_by_key(thrust::device,
// src_begin, src_end, idsrc,
// thrust::greater<float>());
}
void topk(dnnType *src_begin, int *idsrc, int K, float *topk_scores,
int *topk_inds, float *topk_ys, float *topk_xs){
checkCuda( cudaMemcpy(topk_scores, (float *)src_begin, K*sizeof(float), cudaMemcpyDeviceToDevice) );
checkCuda( cudaMemcpy(topk_inds, idsrc, K*sizeof(int), cudaMemcpyDeviceToDevice) );
}
__global__
void sortAndTopK_kernel(dnnType *src_begin, int *idsrc, float *topk_scores, int *topk_inds, float *topk_ys, float *topk_xs,const int size, const int K){
int i = blockDim.x*blockIdx.x + threadIdx.x;
thrust::sort_by_key(thrust::device, src_begin + i * size, src_begin + i * size + size, idsrc + i * size, thrust::greater<float>());
thrust::copy_n(thrust::device, src_begin + i * size, K, topk_scores + i * K);
thrust::copy_n(thrust::device, idsrc + i * size, K, topk_inds + i * K );
}
void sortAndTopKonDevice(dnnType *src_begin, int *idsrc, float *topk_scores, int *topk_inds, float *topk_ys, float *topk_xs, const int size, const int K, const int n_classes){
int blocks = n_classes;
int threads = 1;
sortAndTopK_kernel<<<blocks, threads, 0>>>(src_begin, idsrc, topk_scores, topk_inds, topk_ys, topk_xs, size, K);
}
void topKxyclasses(int *ids_begin, int *ids_end, const int K, const int size, const int wh, int *clses, int *xs, int *ys){
thrust::transform(thrust::device, ids_begin, ids_end, thrust::make_constant_iterator(wh), clses, thrust::divides<int>());
thrust::transform(thrust::device, ids_begin, ids_end, thrust::make_constant_iterator(wh), ids_begin, thrust::modulus<int>());
thrust::transform(thrust::device, ids_begin, ids_end, thrust::make_constant_iterator(size), ys, thrust::divides<int>());
thrust::transform(thrust::device, ids_begin, ids_end, thrust::make_constant_iterator(size), xs, thrust::modulus<int>());
}
void topKxyAddOffset(int * ids_begin, const int K, const int size,
int *intxs_begin, int *intys_begin, float *xs_begin,
float *ys_begin, dnnType *src_begin, float *src_out, int *ids_out){
thrust::gather(thrust::device, ids_begin, ids_begin + K, src_begin, src_out);
thrust::transform(thrust::device, intxs_begin, intxs_begin + K, src_out, xs_begin, thrust::plus<float>());
thrust::transform(thrust::device, ids_begin, ids_begin + K, thrust::make_constant_iterator(size), ids_out, thrust::plus<int>());
thrust::gather(thrust::device, ids_out, ids_out+K, src_begin, src_out);
thrust::transform(thrust::device, intys_begin, intys_begin + K, src_out, ys_begin, thrust::plus<float>());
}
void bboxes(int * ids_begin, const int K, const int size, float *xs_begin, float *ys_begin,
dnnType *src_begin, float *bbx0, float *bbx1, float *bby0, float *bby1,
float *src_out, int *ids_out){
thrust::gather(thrust::device, ids_begin, ids_begin + K, src_begin, src_out);
thrust::transform(thrust::device, src_out, src_out + K, thrust::make_constant_iterator(2), src_out, thrust::divides<float>());
// x0
thrust::transform(thrust::device, xs_begin, xs_begin + K, src_out, bbx0, thrust::minus<float>());
// x1
thrust::transform(thrust::device, xs_begin, xs_begin + K, src_out, bbx1, thrust::plus<float>());
thrust::transform(thrust::device, ids_begin, ids_begin + K, thrust::make_constant_iterator(size), ids_out, thrust::plus<int>());
thrust::gather(thrust::device, ids_out, ids_out + K, src_begin, src_out);
thrust::transform(thrust::device, src_out, src_out + K, thrust::make_constant_iterator(2), src_out, thrust::divides<float>());
// y0
thrust::transform(thrust::device, ys_begin, ys_begin + K, src_out, bby0, thrust::minus<float>());
// y1
thrust::transform(thrust::device, ys_begin, ys_begin + K, src_out, bby1, thrust::plus<float>());
}
+49
View File
@@ -0,0 +1,49 @@
#include "kernels.h"
__global__ void reorg_kernel(int N, float *x, int w, int h, int c, int batch, int stride, int forward, float *out)
{
int i = (blockIdx.x + blockIdx.y*gridDim.x) * blockDim.x + threadIdx.x;
if(i >= N) return;
int in_index = i;
int in_w = i%w;
i = i/w;
int in_h = i%h;
i = i/h;
int in_c = i%c;
i = i/c;
int b = i%batch;
int out_c = c/(stride*stride);
int c2 = in_c % out_c;
int offset = in_c / out_c;
int w2 = in_w*stride + offset % stride;
int h2 = in_h*stride + offset / stride;
//printf("%d\n", offset);
int out_index = w2 + w*stride*(h2 + h*stride*(c2 + out_c*b));
// printf("%d %d %d\n", w2, h2, c2);
//printf("%d %d\n", in_index, out_index);
//if(out_index >= N || out_index < 0) printf("bad bad bad \n");
if(forward) out[out_index] = x[in_index];
else out[in_index] = x[out_index];
//if(forward) out[1] = x[1];
//else out[0] = x[0];
}
/**
reorg function function
*/
void reorgForward(dnnType* srcData, dnnType* dstData,
int n, int c, int h, int w, int stride, cudaStream_t stream) {
int size = n*c*h*w;
int blocks = (size+255)/256;
int threads = 256;
reorg_kernel<<<blocks, threads, 0, stream>>>(size, srcData, w, h, c, n, stride, false, dstData);
}
+46
View File
@@ -0,0 +1,46 @@
#include "kernels.h"
#include <stdio.h>
#define MIN(a,b) (((a)<(b))?(a):(b))
#define MAX(a,b) (((a)>(b))?(a):(b))
__global__ void resize_kernel( int i_N,float *x, int i_w, int i_h, int i_c,
int o_w, int o_h, int o_c, int batch, float *out)
{
int i = (blockIdx.x + blockIdx.y*gridDim.x) * blockDim.x + threadIdx.x;
if(i >= i_N) return;
int out_index = i;
int out_w = i%o_w;
i = i/o_w;
int out_h = i%o_h;
i = i/o_h;
int out_c = i%o_c;
i = i/o_c;
//copying last column/last row as padding
int in_index = ((i*i_c + MIN(out_c,i_c-1))*i_h + MIN(out_h,i_h-1))*i_w + MIN(out_w, i_w-1);
out[out_index] = x[in_index];
}
void resizeForward( dnnType* srcData, dnnType* dstData, int n, int i_c, int i_h, int i_w,
int o_c, int o_h, int o_w, cudaStream_t stream )
{
int i_size = n*i_c*i_h*i_w;
int o_size = n*o_c*o_h*o_w;
int blocks = (o_size+255)/256;
int threads = 256;
if(i_c == o_c && i_h == o_h && i_w == o_w )
{
checkCuda(cudaMemcpy(dstData, srcData, i_size*sizeof(dnnType), cudaMemcpyDeviceToDevice));
}
else
{
checkCuda(cudaMemset(dstData, 0, o_size*sizeof(dnnType)));
resize_kernel<<<blocks, threads, 0, stream>>>(o_size, srcData, i_w, i_h, i_c, o_w, o_h, o_c, n, dstData);
// printDeviceVector(i_size, srcData);
// printDeviceVector(o_size, dstData);
}
}
+16
View File
@@ -0,0 +1,16 @@
#include "kernels.h"
#include <math.h>
__global__ void scal_add_kernel(dnnType* dstData, int size, float alpha, float beta, int inc)
{
int i = (blockIdx.x + blockIdx.y*gridDim.x) * blockDim.x + threadIdx.x;
if (i < size) dstData[i*inc] = dstData[i*inc] * alpha + beta;
}
void scalAdd(dnnType* dstData, int size, float alpha, float beta, int inc, cudaStream_t stream)
{
int blocks = (size+255)/256;
int threads = 256;
scal_add_kernel<<<blocks, threads, 0, stream>>>(dstData, size, alpha, beta, inc);
}

Some files were not shown because too many files have changed in this diff Show More