Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ModelZoo
SOLOv2-pytorch
Commits
01a03aab
Commit
01a03aab
authored
Oct 08, 2018
by
Kai Chen
Browse files
move parallel module to mmcv
parent
63396a32
Changes
16
Show whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
18 additions
and
355 deletions
+18
-355
mmdet/core/__init__.py
mmdet/core/__init__.py
+2
-3
mmdet/core/parallel/__init__.py
mmdet/core/parallel/__init__.py
+0
-7
mmdet/core/parallel/_functions.py
mmdet/core/parallel/_functions.py
+0
-74
mmdet/core/parallel/data_parallel.py
mmdet/core/parallel/data_parallel.py
+0
-9
mmdet/core/parallel/distributed.py
mmdet/core/parallel/distributed.py
+0
-46
mmdet/core/parallel/scatter_gather.py
mmdet/core/parallel/scatter_gather.py
+0
-54
mmdet/datasets/__init__.py
mmdet/datasets/__init__.py
+4
-6
mmdet/datasets/coco.py
mmdet/datasets/coco.py
+1
-1
mmdet/datasets/loader/__init__.py
mmdet/datasets/loader/__init__.py
+1
-2
mmdet/datasets/loader/build_loader.py
mmdet/datasets/loader/build_loader.py
+6
-1
mmdet/datasets/loader/collate.py
mmdet/datasets/loader/collate.py
+0
-70
mmdet/datasets/utils.py
mmdet/datasets/utils.py
+0
-17
mmdet/datasets/utils/__init__.py
mmdet/datasets/utils/__init__.py
+0
-4
mmdet/datasets/utils/data_container.py
mmdet/datasets/utils/data_container.py
+0
-58
tools/test.py
tools/test.py
+2
-1
tools/train.py
tools/train.py
+2
-2
No files found.
mmdet/core/__init__.py
View file @
01a03aab
from
.anchor
import
*
# noqa: F401, F403
from
.anchor
import
*
# noqa: F401, F403
from
.bbox
import
*
# noqa: F401, F403
from
.bbox
import
*
# noqa: F401, F403
from
.mask
import
*
# noqa: F401, F403
from
.mask
import
*
# noqa: F401, F403
from
.losses
import
*
# noqa: F401, F403
from
.loss
import
*
# noqa: F401, F403
from
.eval
import
*
# noqa: F401, F403
from
.evaluation
import
*
# noqa: F401, F403
from
.parallel
import
*
# noqa: F401, F403
from
.post_processing
import
*
# noqa: F401, F403
from
.post_processing
import
*
# noqa: F401, F403
from
.utils
import
*
# noqa: F401, F403
from
.utils
import
*
# noqa: F401, F403
mmdet/core/parallel/__init__.py
deleted
100644 → 0
View file @
63396a32
from
.data_parallel
import
MMDataParallel
from
.distributed
import
MMDistributedDataParallel
from
.scatter_gather
import
scatter
,
scatter_kwargs
__all__
=
[
'MMDataParallel'
,
'MMDistributedDataParallel'
,
'scatter'
,
'scatter_kwargs'
]
mmdet/core/parallel/_functions.py
deleted
100644 → 0
View file @
63396a32
import
torch
from
torch.nn.parallel._functions
import
_get_stream
def
scatter
(
input
,
devices
,
streams
=
None
):
"""Scatters tensor across multiple GPUs.
"""
if
streams
is
None
:
streams
=
[
None
]
*
len
(
devices
)
if
isinstance
(
input
,
list
):
chunk_size
=
(
len
(
input
)
-
1
)
//
len
(
devices
)
+
1
outputs
=
[
scatter
(
input
[
i
],
[
devices
[
i
//
chunk_size
]],
[
streams
[
i
//
chunk_size
]])
for
i
in
range
(
len
(
input
))
]
return
outputs
elif
isinstance
(
input
,
torch
.
Tensor
):
output
=
input
.
contiguous
()
# TODO: copy to a pinned buffer first (if copying from CPU)
stream
=
streams
[
0
]
if
output
.
numel
()
>
0
else
None
with
torch
.
cuda
.
device
(
devices
[
0
]),
torch
.
cuda
.
stream
(
stream
):
output
=
output
.
cuda
(
devices
[
0
],
non_blocking
=
True
)
return
output
else
:
raise
Exception
(
'Unknown type {}.'
.
format
(
type
(
input
)))
def
synchronize_stream
(
output
,
devices
,
streams
):
if
isinstance
(
output
,
list
):
chunk_size
=
len
(
output
)
//
len
(
devices
)
for
i
in
range
(
len
(
devices
)):
for
j
in
range
(
chunk_size
):
synchronize_stream
(
output
[
i
*
chunk_size
+
j
],
[
devices
[
i
]],
[
streams
[
i
]])
elif
isinstance
(
output
,
torch
.
Tensor
):
if
output
.
numel
()
!=
0
:
with
torch
.
cuda
.
device
(
devices
[
0
]):
main_stream
=
torch
.
cuda
.
current_stream
()
main_stream
.
wait_stream
(
streams
[
0
])
output
.
record_stream
(
main_stream
)
else
:
raise
Exception
(
'Unknown type {}.'
.
format
(
type
(
output
)))
def
get_input_device
(
input
):
if
isinstance
(
input
,
list
):
for
item
in
input
:
input_device
=
get_input_device
(
item
)
if
input_device
!=
-
1
:
return
input_device
return
-
1
elif
isinstance
(
input
,
torch
.
Tensor
):
return
input
.
get_device
()
if
input
.
is_cuda
else
-
1
else
:
raise
Exception
(
'Unknown type {}.'
.
format
(
type
(
input
)))
class
Scatter
(
object
):
@
staticmethod
def
forward
(
target_gpus
,
input
):
input_device
=
get_input_device
(
input
)
streams
=
None
if
input_device
==
-
1
:
# Perform CPU to GPU copies in a background stream
streams
=
[
_get_stream
(
device
)
for
device
in
target_gpus
]
outputs
=
scatter
(
input
,
target_gpus
,
streams
)
# Synchronize with the copy stream
if
streams
is
not
None
:
synchronize_stream
(
outputs
,
target_gpus
,
streams
)
return
tuple
(
outputs
)
mmdet/core/parallel/data_parallel.py
deleted
100644 → 0
View file @
63396a32
from
torch.nn.parallel
import
DataParallel
from
.scatter_gather
import
scatter_kwargs
class
MMDataParallel
(
DataParallel
):
def
scatter
(
self
,
inputs
,
kwargs
,
device_ids
):
return
scatter_kwargs
(
inputs
,
kwargs
,
device_ids
,
dim
=
self
.
dim
)
mmdet/core/parallel/distributed.py
deleted
100644 → 0
View file @
63396a32
import
torch
import
torch.distributed
as
dist
import
torch.nn
as
nn
from
torch._utils
import
(
_flatten_dense_tensors
,
_unflatten_dense_tensors
,
_take_tensors
)
from
.scatter_gather
import
scatter_kwargs
class
MMDistributedDataParallel
(
nn
.
Module
):
def
__init__
(
self
,
module
,
dim
=
0
,
broadcast_buffers
=
True
):
super
(
MMDistributedDataParallel
,
self
).
__init__
()
self
.
module
=
module
self
.
dim
=
dim
self
.
broadcast_buffers
=
broadcast_buffers
self
.
broadcast_bucket_size
=
32
*
1024
*
1024
self
.
_sync_params
()
def
_dist_broadcast_coalesced
(
self
,
tensors
,
buffer_size
):
for
tensors
in
_take_tensors
(
tensors
,
buffer_size
):
flat_tensors
=
_flatten_dense_tensors
(
tensors
)
dist
.
broadcast
(
flat_tensors
,
0
)
for
tensor
,
synced
in
zip
(
tensors
,
_unflatten_dense_tensors
(
flat_tensors
,
tensors
)):
tensor
.
copy_
(
synced
)
def
_sync_params
(
self
):
module_states
=
list
(
self
.
module
.
state_dict
().
values
())
if
len
(
module_states
)
>
0
:
self
.
_dist_broadcast_coalesced
(
module_states
,
self
.
broadcast_bucket_size
)
if
self
.
broadcast_buffers
:
buffers
=
[
b
.
data
for
b
in
self
.
module
.
_all_buffers
()]
if
len
(
buffers
)
>
0
:
self
.
_dist_broadcast_coalesced
(
buffers
,
self
.
broadcast_bucket_size
)
def
scatter
(
self
,
inputs
,
kwargs
,
device_ids
):
return
scatter_kwargs
(
inputs
,
kwargs
,
device_ids
,
dim
=
self
.
dim
)
def
forward
(
self
,
*
inputs
,
**
kwargs
):
inputs
,
kwargs
=
self
.
scatter
(
inputs
,
kwargs
,
[
torch
.
cuda
.
current_device
()])
return
self
.
module
(
*
inputs
[
0
],
**
kwargs
[
0
])
mmdet/core/parallel/scatter_gather.py
deleted
100644 → 0
View file @
63396a32
import
torch
from
torch.nn.parallel._functions
import
Scatter
as
OrigScatter
from
._functions
import
Scatter
from
mmdet.datasets.utils
import
DataContainer
def
scatter
(
inputs
,
target_gpus
,
dim
=
0
):
"""Scatter inputs to target gpus.
The only difference from original :func:`scatter` is to add support for
:type:`~mmdet.DataContainer`.
"""
def
scatter_map
(
obj
):
if
isinstance
(
obj
,
torch
.
Tensor
):
return
OrigScatter
.
apply
(
target_gpus
,
None
,
dim
,
obj
)
if
isinstance
(
obj
,
DataContainer
):
if
obj
.
cpu_only
:
return
obj
.
data
else
:
return
Scatter
.
forward
(
target_gpus
,
obj
.
data
)
if
isinstance
(
obj
,
tuple
)
and
len
(
obj
)
>
0
:
return
list
(
zip
(
*
map
(
scatter_map
,
obj
)))
if
isinstance
(
obj
,
list
)
and
len
(
obj
)
>
0
:
out
=
list
(
map
(
list
,
zip
(
*
map
(
scatter_map
,
obj
))))
return
out
if
isinstance
(
obj
,
dict
)
and
len
(
obj
)
>
0
:
out
=
list
(
map
(
type
(
obj
),
zip
(
*
map
(
scatter_map
,
obj
.
items
()))))
return
out
return
[
obj
for
targets
in
target_gpus
]
# After scatter_map is called, a scatter_map cell will exist. This cell
# has a reference to the actual function scatter_map, which has references
# to a closure that has a reference to the scatter_map cell (because the
# fn is recursive). To avoid this reference cycle, we set the function to
# None, clearing the cell
try
:
return
scatter_map
(
inputs
)
finally
:
scatter_map
=
None
def
scatter_kwargs
(
inputs
,
kwargs
,
target_gpus
,
dim
=
0
):
"""Scatter with support for kwargs dictionary"""
inputs
=
scatter
(
inputs
,
target_gpus
,
dim
)
if
inputs
else
[]
kwargs
=
scatter
(
kwargs
,
target_gpus
,
dim
)
if
kwargs
else
[]
if
len
(
inputs
)
<
len
(
kwargs
):
inputs
.
extend
([()
for
_
in
range
(
len
(
kwargs
)
-
len
(
inputs
))])
elif
len
(
kwargs
)
<
len
(
inputs
):
kwargs
.
extend
([{}
for
_
in
range
(
len
(
inputs
)
-
len
(
kwargs
))])
inputs
=
tuple
(
inputs
)
kwargs
=
tuple
(
kwargs
)
return
inputs
,
kwargs
mmdet/datasets/__init__.py
View file @
01a03aab
from
.coco
import
CocoDataset
from
.coco
import
CocoDataset
from
.loader
import
(
collate
,
GroupSampler
,
DistributedGroupSampler
,
from
.loader
import
GroupSampler
,
DistributedGroupSampler
,
build_dataloader
build_dataloader
)
from
.utils
import
to_tensor
,
random_scale
,
show_ann
from
.utils
import
DataContainer
,
to_tensor
,
random_scale
,
show_ann
__all__
=
[
__all__
=
[
'CocoDataset'
,
'collate'
,
'GroupSampler'
,
'DistributedGroupSampler'
,
'CocoDataset'
,
'GroupSampler'
,
'DistributedGroupSampler'
,
'build_dataloader'
,
'DataContainer'
,
'to_tensor'
,
'random_scale'
,
'build_dataloader'
,
'to_tensor'
,
'random_scale'
,
'show_ann'
'show_ann'
]
]
mmdet/datasets/coco.py
View file @
01a03aab
...
@@ -2,13 +2,13 @@ import os.path as osp
...
@@ -2,13 +2,13 @@ import os.path as osp
import
mmcv
import
mmcv
import
numpy
as
np
import
numpy
as
np
from
mmcv.parallel
import
DataContainer
as
DC
from
pycocotools.coco
import
COCO
from
pycocotools.coco
import
COCO
from
torch.utils.data
import
Dataset
from
torch.utils.data
import
Dataset
from
.transforms
import
(
ImageTransform
,
BboxTransform
,
MaskTransform
,
from
.transforms
import
(
ImageTransform
,
BboxTransform
,
MaskTransform
,
Numpy2Tensor
)
Numpy2Tensor
)
from
.utils
import
to_tensor
,
show_ann
,
random_scale
from
.utils
import
to_tensor
,
show_ann
,
random_scale
from
.utils
import
DataContainer
as
DC
class
CocoDataset
(
Dataset
):
class
CocoDataset
(
Dataset
):
...
...
mmdet/datasets/loader/__init__.py
View file @
01a03aab
from
.build_loader
import
build_dataloader
from
.build_loader
import
build_dataloader
from
.collate
import
collate
from
.sampler
import
GroupSampler
,
DistributedGroupSampler
from
.sampler
import
GroupSampler
,
DistributedGroupSampler
__all__
=
[
__all__
=
[
'collate'
,
'GroupSampler'
,
'DistributedGroupSampler'
,
'build_dataloader'
'GroupSampler'
,
'DistributedGroupSampler'
,
'build_dataloader'
]
]
mmdet/datasets/loader/build_loader.py
View file @
01a03aab
from
functools
import
partial
from
functools
import
partial
from
mmcv.runner
import
get_dist_info
from
mmcv.runner
import
get_dist_info
from
mmcv.parallel
import
collate
from
torch.utils.data
import
DataLoader
from
torch.utils.data
import
DataLoader
from
.collate
import
collate
from
.sampler
import
GroupSampler
,
DistributedGroupSampler
from
.sampler
import
GroupSampler
,
DistributedGroupSampler
# https://github.com/pytorch/pytorch/issues/973
import
resource
rlimit
=
resource
.
getrlimit
(
resource
.
RLIMIT_NOFILE
)
resource
.
setrlimit
(
resource
.
RLIMIT_NOFILE
,
(
4096
,
rlimit
[
1
]))
def
build_dataloader
(
dataset
,
def
build_dataloader
(
dataset
,
imgs_per_gpu
,
imgs_per_gpu
,
...
...
mmdet/datasets/loader/collate.py
deleted
100644 → 0
View file @
63396a32
import
collections
import
torch
import
torch.nn.functional
as
F
from
torch.utils.data.dataloader
import
default_collate
from
..utils
import
DataContainer
# https://github.com/pytorch/pytorch/issues/973
import
resource
rlimit
=
resource
.
getrlimit
(
resource
.
RLIMIT_NOFILE
)
resource
.
setrlimit
(
resource
.
RLIMIT_NOFILE
,
(
4096
,
rlimit
[
1
]))
def
collate
(
batch
,
samples_per_gpu
=
1
):
"""Puts each data field into a tensor/DataContainer with outer dimension
batch size.
Extend default_collate to add support for :type:`~mmdet.DataContainer`.
There are 3 cases for data containers.
1. cpu_only = True, e.g., meta data
2. cpu_only = False, stack = True, e.g., images tensors
3. cpu_only = False, stack = False, e.g., gt bboxes
"""
if
not
isinstance
(
batch
,
collections
.
Sequence
):
raise
TypeError
(
"{} is not supported."
.
format
(
batch
.
dtype
))
if
isinstance
(
batch
[
0
],
DataContainer
):
assert
len
(
batch
)
%
samples_per_gpu
==
0
stacked
=
[]
if
batch
[
0
].
cpu_only
:
for
i
in
range
(
0
,
len
(
batch
),
samples_per_gpu
):
stacked
.
append
(
[
sample
.
data
for
sample
in
batch
[
i
:
i
+
samples_per_gpu
]])
return
DataContainer
(
stacked
,
batch
[
0
].
stack
,
batch
[
0
].
padding_value
,
cpu_only
=
True
)
elif
batch
[
0
].
stack
:
for
i
in
range
(
0
,
len
(
batch
),
samples_per_gpu
):
assert
isinstance
(
batch
[
i
].
data
,
torch
.
Tensor
)
# TODO: handle tensors other than 3d
assert
batch
[
i
].
dim
()
==
3
c
,
h
,
w
=
batch
[
0
].
size
()
for
sample
in
batch
[
i
:
i
+
samples_per_gpu
]:
assert
c
==
sample
.
size
(
0
)
h
=
max
(
h
,
sample
.
size
(
1
))
w
=
max
(
w
,
sample
.
size
(
2
))
padded_samples
=
[
F
.
pad
(
sample
.
data
,
(
0
,
w
-
sample
.
size
(
2
),
0
,
h
-
sample
.
size
(
1
)),
value
=
sample
.
padding_value
)
for
sample
in
batch
[
i
:
i
+
samples_per_gpu
]
]
stacked
.
append
(
default_collate
(
padded_samples
))
else
:
for
i
in
range
(
0
,
len
(
batch
),
samples_per_gpu
):
stacked
.
append
(
[
sample
.
data
for
sample
in
batch
[
i
:
i
+
samples_per_gpu
]])
return
DataContainer
(
stacked
,
batch
[
0
].
stack
,
batch
[
0
].
padding_value
)
elif
isinstance
(
batch
[
0
],
collections
.
Sequence
):
transposed
=
zip
(
*
batch
)
return
[
collate
(
samples
,
samples_per_gpu
)
for
samples
in
transposed
]
elif
isinstance
(
batch
[
0
],
collections
.
Mapping
):
return
{
key
:
collate
([
d
[
key
]
for
d
in
batch
],
samples_per_gpu
)
for
key
in
batch
[
0
]
}
else
:
return
default_collate
(
batch
)
mmdet/datasets/utils
/misc
.py
→
mmdet/datasets/utils.py
View file @
01a03aab
...
@@ -5,7 +5,6 @@ import torch
...
@@ -5,7 +5,6 @@ import torch
import
matplotlib.pyplot
as
plt
import
matplotlib.pyplot
as
plt
import
numpy
as
np
import
numpy
as
np
import
pycocotools.mask
as
maskUtils
def
to_tensor
(
data
):
def
to_tensor
(
data
):
...
@@ -68,19 +67,3 @@ def show_ann(coco, img, ann_info):
...
@@ -68,19 +67,3 @@ def show_ann(coco, img, ann_info):
plt
.
axis
(
'off'
)
plt
.
axis
(
'off'
)
coco
.
showAnns
(
ann_info
)
coco
.
showAnns
(
ann_info
)
plt
.
show
()
plt
.
show
()
def
draw_bbox_and_segm
(
img
,
results
,
dataset
,
score_thr
=
0.5
):
bbox_results
,
segm_results
=
results
hi_bboxes
=
[]
for
cls_bboxes
,
cls_segms
in
zip
(
bbox_results
,
segm_results
):
if
len
(
cls_bboxes
)
==
0
:
hi_bboxes
.
append
(
cls_bboxes
)
continue
inds
=
np
.
where
(
cls_bboxes
[:,
-
1
]
>
score_thr
)[
0
]
hi_bboxes
.
append
(
cls_bboxes
[
inds
,
:])
color_mask
=
np
.
random
.
random
((
1
,
3
))
for
i
in
inds
:
mask
=
maskUtils
.
decode
(
cls_segms
[
i
]).
astype
(
np
.
bool
)
img
[
mask
]
=
img
[
mask
]
*
0.5
+
color_mask
*
0.5
mmcv
.
draw_bboxes_with_label
(
np
.
ascontiguousarray
(
img
),
hi_bboxes
,
dataset
)
mmdet/datasets/utils/__init__.py
deleted
100644 → 0
View file @
63396a32
from
.data_container
import
DataContainer
from
.misc
import
to_tensor
,
random_scale
,
show_ann
__all__
=
[
'DataContainer'
,
'to_tensor'
,
'random_scale'
,
'show_ann'
]
mmdet/datasets/utils/data_container.py
deleted
100644 → 0
View file @
63396a32
import
functools
import
torch
def
assert_tensor_type
(
func
):
@
functools
.
wraps
(
func
)
def
wrapper
(
*
args
,
**
kwargs
):
if
not
isinstance
(
args
[
0
].
data
,
torch
.
Tensor
):
raise
AttributeError
(
'{} has no attribute {} for type {}'
.
format
(
args
[
0
].
__class__
.
__name__
,
func
.
__name__
,
args
[
0
].
datatype
))
return
func
(
*
args
,
**
kwargs
)
return
wrapper
class
DataContainer
(
object
):
def
__init__
(
self
,
data
,
stack
=
False
,
padding_value
=
0
,
cpu_only
=
False
):
self
.
_data
=
data
self
.
_cpu_only
=
cpu_only
self
.
_stack
=
stack
self
.
_padding_value
=
padding_value
def
__repr__
(
self
):
return
'{}({})'
.
format
(
self
.
__class__
.
__name__
,
repr
(
self
.
data
))
@
property
def
data
(
self
):
return
self
.
_data
@
property
def
datatype
(
self
):
if
isinstance
(
self
.
data
,
torch
.
Tensor
):
return
self
.
data
.
type
()
else
:
return
type
(
self
.
data
)
@
property
def
cpu_only
(
self
):
return
self
.
_cpu_only
@
property
def
stack
(
self
):
return
self
.
_stack
@
property
def
padding_value
(
self
):
return
self
.
_padding_value
@
assert_tensor_type
def
size
(
self
,
*
args
,
**
kwargs
):
return
self
.
data
.
size
(
*
args
,
**
kwargs
)
@
assert_tensor_type
def
dim
(
self
):
return
self
.
data
.
dim
()
tools/test.py
View file @
01a03aab
...
@@ -3,9 +3,10 @@ import argparse
...
@@ -3,9 +3,10 @@ import argparse
import
torch
import
torch
import
mmcv
import
mmcv
from
mmcv.runner
import
load_checkpoint
,
parallel_test
,
obj_from_dict
from
mmcv.runner
import
load_checkpoint
,
parallel_test
,
obj_from_dict
from
mmcv.parallel
import
scatter
,
MMDataParallel
from
mmdet
import
datasets
from
mmdet
import
datasets
from
mmdet.core
import
scatter
,
MMDataParallel
,
results2json
,
coco_eval
from
mmdet.core
import
results2json
,
coco_eval
from
mmdet.datasets
import
collate
,
build_dataloader
from
mmdet.datasets
import
collate
,
build_dataloader
from
mmdet.models
import
build_detector
,
detectors
from
mmdet.models
import
build_detector
,
detectors
...
...
tools/train.py
View file @
01a03aab
...
@@ -9,10 +9,10 @@ import numpy as np
...
@@ -9,10 +9,10 @@ import numpy as np
import
torch
import
torch
from
mmcv
import
Config
from
mmcv
import
Config
from
mmcv.runner
import
Runner
,
obj_from_dict
,
DistSamplerSeedHook
from
mmcv.runner
import
Runner
,
obj_from_dict
,
DistSamplerSeedHook
from
mmcv.parallel
import
MMDataParallel
,
MMDistributedDataParallel
from
mmdet
import
datasets
,
__version__
from
mmdet
import
datasets
,
__version__
from
mmdet.core
import
(
init_dist
,
DistOptimizerHook
,
MMDataParallel
,
from
mmdet.core
import
(
init_dist
,
DistOptimizerHook
,
CocoDistEvalRecallHook
,
MMDistributedDataParallel
,
CocoDistEvalRecallHook
,
CocoDistEvalmAPHook
)
CocoDistEvalmAPHook
)
from
mmdet.datasets
import
build_dataloader
from
mmdet.datasets
import
build_dataloader
from
mmdet.models
import
build_detector
,
RPN
from
mmdet.models
import
build_detector
,
RPN
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment