public void Forward(K210UploadLayerArgument argument, ForwardContext context) { var src = context.GetMainRamAt((int)argument.MainMemoryInputAddress); var dest = context.GetKpuRamAt((int)argument.KPUMemoryOutputAddress); K210Helper.KpuUpload(dest, src, (int)argument.Width, (int)argument.Height, (int)argument.Channels); }
public K210Conv2dLayerArgument Convert(K210Conv2d layer, ConvertContext context) { var config = new K210ConvLayerConfig { BNConfigs = new K210LayerBNConfig[layer.OutputChannels], ActConfigs = new K210LayerActConfig[16] }; (var sw, var bw) = QuantizeWeights(layer.Conv2dType == K210Conv2dType.Conv2d, layer.Weights, config, context.WeightsBits); (var sx, var bx) = QuantizeInput(context.Quantization.Distributions[layer.Input.Connection.From].Global, config); config.ArgAdd = (long)Math.Round(bw * bx * layer.KernelWidth * layer.KernelHeight); var scale = new double[layer.OutputChannels]; for (int i = 0; i < scale.Length; i++) { scale[i] = sw[i] * sx; } QuantizeBiasAndOutput(layer, layer.Bias, context.Quantization.Distributions[layer.Output], context.Quantization.AdditionalDistributions[layer.OutputBeforeActivation], scale, config); config.InputChannels = layer.InputChannels; config.OutputChannels = layer.OutputChannels; config.InputWidth = layer.Input.Dimensions[3]; config.InputHeight = layer.Input.Dimensions[2]; (config.InputGroups, config.InputRowLength) = K210Helper.GetRowLayout(config.InputWidth); config.OutputWidth = layer.Output.Dimensions[3]; config.OutputHeight = layer.Output.Dimensions[2]; (config.OutputGroups, config.OutputRowLength) = K210Helper.GetRowLayout(config.OutputWidth); config.KernelType = layer.KernelWidth == 3 ? 1 : 0; config.IsDepthwise = layer.Conv2dType == K210Conv2dType.DepthwiseConv2d; config.PoolType = (int)layer.PoolType; config.PadValue = (int)Math.Round(-bx); if (layer.Conv2dType == K210Conv2dType.Conv2d) { var kernelSize = (int)layer.Weights.Length * context.WeightsBits / 8; var oneChannelSize = layer.KernelWidth * layer.KernelHeight * layer.InputChannels * context.WeightsBits / 8; var sizeLimit = context.WeightsBits == 8 ? 30 : 60; var oneLoadChannels = Math.Min(layer.OutputChannels, (int)Math.Floor(sizeLimit * 1024.0 / oneChannelSize)); config.OneLoadKernelsSize = oneChannelSize * oneLoadChannels; config.LoadTimes = (int)Math.Ceiling(layer.OutputChannels / (double)oneLoadChannels); config.OutputChannelsOnTime = oneLoadChannels; } else { config.OneLoadKernelsSize = (int)layer.Weights.Length * context.WeightsBits / 8; config.LoadTimes = 1; config.OutputChannelsOnTime = layer.OutputChannels; } var inputOneLineChannels = Math.Min(layer.InputChannels, config.InputGroups); config.InputSize = config.InputRowLength * config.InputHeight * config.InputChannels / inputOneLineChannels; var outputOneLineChannels = Math.Min(layer.OutputChannels, config.OutputGroups); config.OutputSize = config.OutputRowLength * config.OutputHeight * config.OutputChannels / outputOneLineChannels; return(new K210Conv2dLayerArgument { Config = config, ParamAddress = new K210Conv2dParamAddress() }); }