Browse Source

unroll size 4 for conv1x1s1 pack4

tags/20190611
nihuini 7 years ago
parent
commit
74276314bb
3 changed files with 207 additions and 14 deletions
  1. +51
    -14
      src/layer/vulkan/convolution_vulkan.cpp
  2. +1
    -0
      src/layer/vulkan/convolution_vulkan.h
  3. +155
    -0
      src/layer/vulkan/shader/convolution_pack4_1x1s1d1.comp

+ 51
- 14
src/layer/vulkan/convolution_vulkan.cpp View File

@@ -29,6 +29,7 @@ Convolution_vulkan::Convolution_vulkan()
pipeline_convolution = 0;
pipeline_convolution_1x1s1d1 = 0;
pipeline_convolution_pack4 = 0;
pipeline_convolution_pack4_1x1s1d1 = 0;
pipeline_convolution_pack4_3x3s1d1_lds_8_8_2 = 0;
winograd23_padding = 0;
winograd23_crop = 0;
@@ -63,20 +64,6 @@ int Convolution_vulkan::create_pipeline(const Option& opt)
padding->create_pipeline(opt);
}

if (kernel_w == 1 && kernel_h == 1 && stride_w == 1 && stride_h == 1 && dilation_w == 1 && dilation_h == 1)
{
pipeline_convolution_1x1s1d1 = new Pipeline(vkdev);
pipeline_convolution_1x1s1d1->set_optimal_local_size_xyz(-1, 1, std::max(1, num_output / 8));

std::vector<vk_specialization_type> specializations(4);
specializations[0].i = bias_term;
specializations[1].i = activation_type;
specializations[2].f = activation_params.w == 1 ? activation_params[0] : 0.f;
specializations[3].f = activation_params.w == 2 ? activation_params[1] : 0.f;

pipeline_convolution_1x1s1d1->create("convolution_1x1s1d1", specializations, 4, 8);
}

const int maxk = kernel_w * kernel_h;
int num_input = weight_data_size / maxk / num_output;

@@ -98,6 +85,20 @@ int Convolution_vulkan::create_pipeline(const Option& opt)
pipeline_convolution = new Pipeline(vkdev);
pipeline_convolution->set_optimal_local_size_xyz(32, 32, std::max(1, num_output / 8));
pipeline_convolution->create("convolution", specializations, 4, 10);

if (kernel_w == 1 && kernel_h == 1 && stride_w == 1 && stride_h == 1 && dilation_w == 1 && dilation_h == 1)
{
pipeline_convolution_1x1s1d1 = new Pipeline(vkdev);
pipeline_convolution_1x1s1d1->set_optimal_local_size_xyz(-1, 1, std::max(1, num_output / 8));

std::vector<vk_specialization_type> specializations(4);
specializations[0].i = bias_term;
specializations[1].i = activation_type;
specializations[2].f = activation_params.w == 1 ? activation_params[0] : 0.f;
specializations[3].f = activation_params.w == 2 ? activation_params[1] : 0.f;

pipeline_convolution_1x1s1d1->create("convolution_1x1s1d1", specializations, 4, 8);
}
}

// pack4
@@ -107,6 +108,20 @@ int Convolution_vulkan::create_pipeline(const Option& opt)
pipeline_convolution_pack4->set_optimal_local_size_xyz(32, 32, std::max(1, num_output / 8));
pipeline_convolution_pack4->create("convolution_pack4", specializations, 4, 10);

if (kernel_w == 1 && kernel_h == 1 && stride_w == 1 && stride_h == 1 && dilation_w == 1 && dilation_h == 1)
{
pipeline_convolution_pack4_1x1s1d1 = new Pipeline(vkdev);
pipeline_convolution_pack4_1x1s1d1->set_local_size_xyz(8, 1, std::min(8, num_output / 2));

std::vector<vk_specialization_type> specializations(4);
specializations[0].i = bias_term;
specializations[1].i = activation_type;
specializations[2].f = activation_params.w == 1 ? activation_params[0] : 0.f;
specializations[3].f = activation_params.w == 2 ? activation_params[1] : 0.f;

pipeline_convolution_pack4_1x1s1d1->create("convolution_pack4_1x1s1d1", specializations, 4, 8);
}

if (kernel_w == 3 && kernel_h == 3 && stride_w == 1 && stride_h == 1 && dilation_w == 1 && dilation_h == 1)
{
std::vector<vk_specialization_type> specializations(4);
@@ -249,6 +264,9 @@ int Convolution_vulkan::destroy_pipeline(const Option& opt)
delete pipeline_convolution_pack4;
pipeline_convolution_pack4 = 0;

delete pipeline_convolution_pack4_1x1s1d1;
pipeline_convolution_pack4_1x1s1d1 = 0;

delete pipeline_convolution_pack4_3x3s1d1_lds_8_8_2;
pipeline_convolution_pack4_3x3s1d1_lds_8_8_2 = 0;

@@ -929,6 +947,25 @@ int Convolution_vulkan::forward(const VkMat& bottom_blob, VkMat& top_blob, VkCom

cmd.record_pipeline(pipeline_convolution_1x1s1d1, bindings, constants, dispatcher);
}
else if (packing == 4 && out_packing == 4 && kernel_w == 1 && kernel_h == 1 && stride_w == 1 && stride_h == 1 && dilation_w == 1 && dilation_h == 1)
{
std::vector<vk_constant_type> constants(8);
constants[0].i = bottom_blob_bordered.dims;
constants[1].i = (bottom_blob_bordered.cstep + 3) / 4;
constants[2].i = bottom_blob_bordered.c;
constants[3].i = bottom_blob_bordered.cstep;
constants[4].i = top_blob.dims;
constants[5].i = (top_blob.cstep + 3) / 4;
constants[6].i = top_blob.c;
constants[7].i = top_blob.cstep;

VkMat dispatcher;
dispatcher.w = (top_blob.cstep + 3) / 4;
dispatcher.h = 1;
dispatcher.c = top_blob.c;

cmd.record_pipeline(pipeline_convolution_pack4_1x1s1d1, bindings, constants, dispatcher);
}
else if (packing == 4 && out_packing == 4 && kernel_w == 3 && kernel_h == 3 && stride_w == 1 && stride_h == 1 && dilation_w == 1 && dilation_h == 1)
{
std::vector<vk_constant_type> constants(10);


+ 1
- 0
src/layer/vulkan/convolution_vulkan.h View File

@@ -45,6 +45,7 @@ public:
// pack4
VkMat weight_data_gpu_pack4;
Pipeline* pipeline_convolution_pack4;
Pipeline* pipeline_convolution_pack4_1x1s1d1;
Pipeline* pipeline_convolution_pack4_3x3s1d1_lds_8_8_2;

// pack4 winograd23


+ 155
- 0
src/layer/vulkan/shader/convolution_pack4_1x1s1d1.comp View File

@@ -0,0 +1,155 @@
// Tencent is pleased to support the open source community by making ncnn available.
//
// Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
//
// Licensed under the BSD 3-Clause License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
//
// https://opensource.org/licenses/BSD-3-Clause
//
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.

#version 450

#if NCNN_fp16_storage
#extension GL_EXT_shader_16bit_storage: require
#endif
#if NCNN_fp16_arithmetic
#extension GL_AMD_gpu_shader_half_float: require
#endif

layout (constant_id = 0) const int bias_term = 0;
layout (constant_id = 1) const int activation_type = 0;
layout (constant_id = 2) const float activation_param_0 = 0;
layout (constant_id = 3) const float activation_param_1 = 0;

layout (local_size_x_id = 233) in;
layout (local_size_y_id = 234) in;
layout (local_size_z_id = 235) in;

layout (binding = 0) readonly buffer bottom_blob { sfpvec4 bottom_blob_data[]; };
layout (binding = 1) writeonly buffer top_blob { sfpvec4 top_blob_data[]; };
#if NCNN_fp16_packed || (NCNN_fp16_storage && !NCNN_fp16_arithmetic)
// GL_EXT_shader_16bit_storage does not define f16mat4 type :(
layout (binding = 2) readonly buffer weight_blob { sfpvec4 weight_data[]; };
#else
layout (binding = 2) readonly buffer weight_blob { sfpmat4 weight_data[]; };
#endif
layout (binding = 3) readonly buffer bias_blob { sfpvec4 bias_data[]; };

layout (push_constant) uniform parameter
{
int dims;
int size_4;
int c;
int cstep;

int outdims;
int outsize_4;
int outc;
int outcstep;
} p;

void main()
{
int gx = int(gl_GlobalInvocationID.x);
int gy = int(gl_GlobalInvocationID.y);
int gz = int(gl_GlobalInvocationID.z);

if (gx >= p.outsize_4 || gy >= 1 || gz >= p.outc)
return;

afpvec4 sum0;
afpvec4 sum1;
afpvec4 sum2;
afpvec4 sum3;

if (bias_term == 1)
{
afpvec4 b = sfp2afpvec4(bias_data[gz]);
sum0 = b;
sum1 = b;
sum2 = b;
sum3 = b;
}
else
{
sum0 = afpvec4(0.f);
sum1 = afpvec4(0.f);
sum2 = afpvec4(0.f);
sum3 = afpvec4(0.f);
}

int w_offset = gz * p.c;
int v_offset = gx * 4;

for (int z = 0; z < p.c; z++)
{
afpvec4 v0 = sfp2afpvec4(bottom_blob_data[v_offset + 0]);
afpvec4 v1 = sfp2afpvec4(bottom_blob_data[v_offset + 1]);
afpvec4 v2 = sfp2afpvec4(bottom_blob_data[v_offset + 2]);
afpvec4 v3 = sfp2afpvec4(bottom_blob_data[v_offset + 3]);

#if NCNN_fp16_packed || (NCNN_fp16_storage && !NCNN_fp16_arithmetic)
// GL_EXT_shader_16bit_storage does not define f16mat4 type :(
afpmat4 k = afpmat4(
sfp2afpvec4(weight_data[w_offset * 4 + 0]),
sfp2afpvec4(weight_data[w_offset * 4 + 1]),
sfp2afpvec4(weight_data[w_offset * 4 + 2]),
sfp2afpvec4(weight_data[w_offset * 4 + 3])
);
#else
afpmat4 k = sfp2afpmat4(weight_data[w_offset]);
#endif

sum0 += v0 * k;
sum1 += v1 * k;
sum2 += v2 * k;
sum3 += v3 * k;

w_offset += 1;
v_offset += p.cstep;
}

if (activation_type == 1)
{
sum0 = max(sum0, afp(0.f));
sum1 = max(sum1, afp(0.f));
sum2 = max(sum2, afp(0.f));
sum3 = max(sum3, afp(0.f));
}
if (activation_type == 2)
{
const afp slope = afp(activation_param_0);
sum0 = mix(sum0, sum0 * afp(slope), lessThan(sum0, afpvec4(0.f)));
sum1 = mix(sum1, sum1 * afp(slope), lessThan(sum1, afpvec4(0.f)));
sum2 = mix(sum2, sum2 * afp(slope), lessThan(sum2, afpvec4(0.f)));
sum3 = mix(sum3, sum3 * afp(slope), lessThan(sum3, afpvec4(0.f)));
}
if (activation_type == 3)
{
const afp const_min = afp(activation_param_0);
const afp const_max = afp(activation_param_1);
sum0 = clamp(sum0, const_min, const_max);
sum1 = clamp(sum1, const_min, const_max);
sum2 = clamp(sum2, const_min, const_max);
sum3 = clamp(sum3, const_min, const_max);
}
if (activation_type == 4)
{
sum0 = afp(1.f) / (afp(1.f) + exp(-sum0));
sum1 = afp(1.f) / (afp(1.f) + exp(-sum1));
sum2 = afp(1.f) / (afp(1.f) + exp(-sum2));
sum3 = afp(1.f) / (afp(1.f) + exp(-sum3));
}

int gi = gz * p.outcstep + gx * 4;

top_blob_data[gi + 0] = afp2sfpvec4(sum0);
if (gx * 4 + 1 < p.outcstep) top_blob_data[gi + 1] = afp2sfpvec4(sum1);
if (gx * 4 + 2 < p.outcstep) top_blob_data[gi + 2] = afp2sfpvec4(sum2);
if (gx * 4 + 3 < p.outcstep) top_blob_data[gi + 3] = afp2sfpvec4(sum3);
}

Loading…
Cancel
Save