Skip to content

Commit 7d5d32d

Browse files
authored
vulkan upload weights per layer, reduce peak ram usage (#6534)
1 parent ec19da2 commit 7d5d32d

3 files changed

Lines changed: 131 additions & 54 deletions

File tree

src/command.cpp

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2288,6 +2288,8 @@ class VkTransferPrivate
22882288

22892289
const VulkanDevice* vkdev;
22902290

2291+
uint64_t pending_upload_total;
2292+
22912293
VkCommandPool compute_command_pool;
22922294
VkCommandPool transfer_command_pool;
22932295

@@ -2305,6 +2307,8 @@ class VkTransferPrivate
23052307
VkTransferPrivate::VkTransferPrivate(const VulkanDevice* _vkdev)
23062308
: vkdev(_vkdev)
23072309
{
2310+
pending_upload_total = 0;
2311+
23082312
compute_command_pool = 0;
23092313
transfer_command_pool = 0;
23102314

@@ -2569,6 +2573,8 @@ void VkTransfer::record_upload(const Mat& src, VkMat& dst, const Option& opt, bo
25692573
return;
25702574
}
25712575

2576+
d->pending_upload_total += dst.total() * dst.elemsize;
2577+
25722578
if (dst.allocator->mappable)
25732579
{
25742580
// memcpy src_flattened to device
@@ -2843,9 +2849,65 @@ int VkTransfer::submit_and_wait()
28432849
}
28442850
}
28452851

2852+
d->pending_upload_total = 0;
2853+
28462854
return 0;
28472855
}
28482856

2857+
int VkTransfer::reset()
2858+
{
2859+
d->upload_staging_buffers.clear();
2860+
2861+
d->pending_upload_total = 0;
2862+
2863+
// reset command buffer and fence
2864+
{
2865+
VkResult ret = vkResetCommandBuffer(d->compute_command_buffer, 0);
2866+
if (ret != VK_SUCCESS)
2867+
{
2868+
NCNN_LOGE("vkResetCommandBuffer failed %d", ret);
2869+
return -1;
2870+
}
2871+
}
2872+
{
2873+
VkResult ret = vkResetFences(vkdev->vkdevice(), 1, &d->compute_command_fence);
2874+
if (ret != VK_SUCCESS)
2875+
{
2876+
NCNN_LOGE("vkResetFences failed %d", ret);
2877+
return -1;
2878+
}
2879+
}
2880+
2881+
if (!vkdev->info.unified_compute_transfer_queue())
2882+
{
2883+
{
2884+
VkResult ret = vkResetCommandBuffer(d->upload_command_buffer, 0);
2885+
if (ret != VK_SUCCESS)
2886+
{
2887+
NCNN_LOGE("vkResetCommandBuffer failed %d", ret);
2888+
return -1;
2889+
}
2890+
}
2891+
{
2892+
VkResult ret = vkResetFences(vkdev->vkdevice(), 1, &d->upload_command_fence);
2893+
if (ret != VK_SUCCESS)
2894+
{
2895+
NCNN_LOGE("vkResetFences failed %d", ret);
2896+
return -1;
2897+
}
2898+
}
2899+
}
2900+
2901+
d->begin_command_buffer();
2902+
2903+
return 0;
2904+
}
2905+
2906+
uint64_t VkTransfer::pending_upload_total() const
2907+
{
2908+
return d->pending_upload_total;
2909+
}
2910+
28492911
} // namespace ncnn
28502912

28512913
#endif // NCNN_VULKAN

src/command.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,10 @@ class NCNN_EXPORT VkTransfer
9797

9898
int submit_and_wait();
9999

100+
int reset();
101+
102+
uint64_t pending_upload_total() const;
103+
100104
protected:
101105
const VulkanDevice* vkdev;
102106

src/net.cpp

Lines changed: 65 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,6 @@ class NetPrivate
3131

3232
Option& opt;
3333

34-
#if NCNN_VULKAN
35-
36-
int upload_model();
37-
38-
#endif // NCNN_VULKAN
39-
4034
friend class Extractor;
4135
int forward_layer(int layer_index, std::vector<Mat>& blob_mats, const Option& opt) const;
4236

@@ -122,52 +116,6 @@ static Option get_masked_option(const Option& opt, int featmask)
122116
return opt1;
123117
}
124118

125-
#if NCNN_VULKAN
126-
int NetPrivate::upload_model()
127-
{
128-
ncnn::VkTransfer cmd(vkdev);
129-
130-
// create gpu device allocator if null
131-
if (!weight_vkallocator)
132-
{
133-
if (opt.use_weights_in_host_memory)
134-
{
135-
weight_vkallocator = new VkHostAllocator(vkdev);
136-
}
137-
else
138-
{
139-
weight_vkallocator = new VkWeightAllocator(vkdev);
140-
}
141-
}
142-
if (!weight_staging_vkallocator)
143-
{
144-
weight_staging_vkallocator = new VkWeightStagingAllocator(vkdev);
145-
}
146-
147-
Option opt_upload = opt;
148-
opt_upload.blob_allocator = 0;
149-
opt_upload.workspace_allocator = 0;
150-
opt_upload.blob_vkallocator = weight_vkallocator;
151-
opt_upload.workspace_vkallocator = weight_vkallocator;
152-
opt_upload.staging_vkallocator = weight_staging_vkallocator;
153-
154-
for (size_t i = 0; i < layers.size(); i++)
155-
{
156-
if (layers[i]->support_vulkan)
157-
{
158-
int uret = layers[i]->upload_model(cmd, get_masked_option(opt_upload, layers[i]->featmask));
159-
if (uret != 0)
160-
{
161-
NCNN_LOGE("layer upload_model %d failed", (int)i);
162-
return -1;
163-
}
164-
}
165-
}
166-
167-
return cmd.submit_and_wait();
168-
}
169-
#endif // NCNN_VULKAN
170-
171119
int NetPrivate::forward_layer(int layer_index, std::vector<Mat>& blob_mats, const Option& opt) const
172120
{
173121
const Layer* layer = layers[layer_index];
@@ -1633,6 +1581,9 @@ int Net::load_model(const DataReader& dr)
16331581
int ret = 0;
16341582

16351583
#if NCNN_VULKAN
1584+
ncnn::VkTransfer* cmd_upload = 0;
1585+
Option opt_upload = opt;
1586+
16361587
if (opt.use_vulkan_compute)
16371588
{
16381589
if (!opt.pipeline_cache)
@@ -1641,6 +1592,31 @@ int Net::load_model(const DataReader& dr)
16411592
d->pipeline_cache = new PipelineCache(d->vkdev);
16421593
opt.pipeline_cache = d->pipeline_cache;
16431594
}
1595+
1596+
cmd_upload = new ncnn::VkTransfer(d->vkdev);
1597+
1598+
// create gpu device allocator if null
1599+
if (!d->weight_vkallocator)
1600+
{
1601+
if (opt.use_weights_in_host_memory)
1602+
{
1603+
d->weight_vkallocator = new VkHostAllocator(d->vkdev);
1604+
}
1605+
else
1606+
{
1607+
d->weight_vkallocator = new VkWeightAllocator(d->vkdev);
1608+
}
1609+
}
1610+
if (!d->weight_staging_vkallocator)
1611+
{
1612+
d->weight_staging_vkallocator = new VkWeightStagingAllocator(d->vkdev);
1613+
}
1614+
1615+
opt_upload.blob_allocator = 0;
1616+
opt_upload.workspace_allocator = 0;
1617+
opt_upload.blob_vkallocator = d->weight_vkallocator;
1618+
opt_upload.workspace_vkallocator = d->weight_vkallocator;
1619+
opt_upload.staging_vkallocator = d->weight_staging_vkallocator;
16441620
}
16451621
#endif // NCNN_VULKAN
16461622

@@ -1682,6 +1658,36 @@ int Net::load_model(const DataReader& dr)
16821658
ret = -1;
16831659
break;
16841660
}
1661+
1662+
#if NCNN_VULKAN
1663+
if (layer->support_vulkan && opt.use_vulkan_compute && cmd_upload)
1664+
{
1665+
int uret = layer->upload_model(*cmd_upload, get_masked_option(opt_upload, layer->featmask));
1666+
if (uret != 0)
1667+
{
1668+
#if NCNN_STRING
1669+
NCNN_LOGE("layer upload_model %d %s failed", i, layer->name.c_str());
1670+
#else
1671+
NCNN_LOGE("layer upload_model %d failed", i);
1672+
#endif
1673+
ret = -1;
1674+
break;
1675+
}
1676+
1677+
// commit as soon as we collect 256M pending
1678+
if (cmd_upload->pending_upload_total() > 256 * 1024 * 1024)
1679+
{
1680+
uret = cmd_upload->submit_and_wait();
1681+
if (uret != 0)
1682+
{
1683+
ret = -1;
1684+
break;
1685+
}
1686+
1687+
cmd_upload->reset();
1688+
}
1689+
}
1690+
#endif // NCNN_VULKAN
16851691
}
16861692

16871693
if (opt.use_local_pool_allocator)
@@ -1705,9 +1711,14 @@ int Net::load_model(const DataReader& dr)
17051711
}
17061712

17071713
#if NCNN_VULKAN
1708-
if (ret == 0 && opt.use_vulkan_compute)
1714+
if (ret == 0 && opt.use_vulkan_compute && cmd_upload)
1715+
{
1716+
ret = cmd_upload->submit_and_wait();
1717+
}
1718+
1719+
if (cmd_upload)
17091720
{
1710-
ret = d->upload_model();
1721+
delete cmd_upload;
17111722
}
17121723
#endif // NCNN_VULKAN
17131724

0 commit comments

Comments
 (0)