mirror of
https://github.com/saymrwulf/onnxruntime.git
synced 2026-07-29 20:14:01 +00:00
[js/webgpu] Add hardSigmoid activation for fusedConv (#19233)
### Description Add hardSigmoid activation for fusedConv. It will be used by mobilenetv3-small-100 model.
This commit is contained in:
parent
8dad9d92f4
commit
90883a366a
8 changed files with 207 additions and 57 deletions
|
|
@ -24,7 +24,7 @@ import {TensorView} from '../../../tensor-view';
|
||||||
import {ProgramInfo, ProgramInputTensorInfoDependency, ProgramUniform} from '../../types';
|
import {ProgramInfo, ProgramInputTensorInfoDependency, ProgramUniform} from '../../types';
|
||||||
import {createTensorShapeVariables, inputVariable, outputVariable, ShaderHelper, tensorTypeToWsglStorageType, UniformsArrayType} from '../common';
|
import {createTensorShapeVariables, inputVariable, outputVariable, ShaderHelper, tensorTypeToWsglStorageType, UniformsArrayType} from '../common';
|
||||||
import {ConvAttributes} from '../conv';
|
import {ConvAttributes} from '../conv';
|
||||||
import {getActivationSnippet} from '../fuse-utils';
|
import {appendActivationUniforms, appendActivationUniformsData, getActivationSnippet} from '../fuse-utils';
|
||||||
|
|
||||||
import {biasSnippet, typeSnippet} from './activation_util';
|
import {biasSnippet, typeSnippet} from './activation_util';
|
||||||
import {utilFunctions} from './conv_util';
|
import {utilFunctions} from './conv_util';
|
||||||
|
|
@ -193,10 +193,7 @@ export const createConv2DMatMulProgramInfo =
|
||||||
{type: 'int32', data: [attributes.pads[0], attributes.pads[1]]}, {type: 'int32', data: attributes.strides},
|
{type: 'int32', data: [attributes.pads[0], attributes.pads[1]]}, {type: 'int32', data: attributes.strides},
|
||||||
{type: 'int32', data: attributes.dilations}
|
{type: 'int32', data: attributes.dilations}
|
||||||
];
|
];
|
||||||
if (attributes.activation === 'Clip') {
|
appendActivationUniformsData(attributes, programUniforms);
|
||||||
programUniforms.push(
|
|
||||||
{type: 'float32', data: attributes.clipMax!}, {type: 'float32', data: attributes.clipMin!});
|
|
||||||
}
|
|
||||||
programUniforms.push(
|
programUniforms.push(
|
||||||
...createTensorShapeVariables(inputs[0].dims), ...createTensorShapeVariables(inputs[1].dims));
|
...createTensorShapeVariables(inputs[0].dims), ...createTensorShapeVariables(inputs[1].dims));
|
||||||
const inputDependencies: ProgramInputTensorInfoDependency[] = ['rank', 'rank'];
|
const inputDependencies: ProgramInputTensorInfoDependency[] = ['rank', 'rank'];
|
||||||
|
|
@ -212,9 +209,7 @@ export const createConv2DMatMulProgramInfo =
|
||||||
{name: 'pad', type: 'i32', length: 2}, {name: 'stride', type: 'i32', length: 2},
|
{name: 'pad', type: 'i32', length: 2}, {name: 'stride', type: 'i32', length: 2},
|
||||||
{name: 'dilation', type: 'i32', length: 2}
|
{name: 'dilation', type: 'i32', length: 2}
|
||||||
];
|
];
|
||||||
if (attributes.activation === 'Clip') {
|
appendActivationUniforms(attributes, uniforms);
|
||||||
uniforms.push({name: 'clip_max', type: 'f32'}, {name: 'clip_min', type: 'f32'});
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: support component 2, 3.
|
// TODO: support component 2, 3.
|
||||||
const components = isVec4 ? 4 : 1;
|
const components = isVec4 ? 4 : 1;
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ import {TensorView} from '../../../tensor-view';
|
||||||
import {ProgramInfo, ProgramInputTensorInfoDependency, ProgramUniform} from '../../types';
|
import {ProgramInfo, ProgramInputTensorInfoDependency, ProgramUniform} from '../../types';
|
||||||
import {createTensorShapeVariables, inputVariable, outputVariable, ShaderHelper, UniformsArrayType} from '../common';
|
import {createTensorShapeVariables, inputVariable, outputVariable, ShaderHelper, UniformsArrayType} from '../common';
|
||||||
import {ConvTransposeAttributes} from '../conv-transpose';
|
import {ConvTransposeAttributes} from '../conv-transpose';
|
||||||
import {getActivationSnippet} from '../fuse-utils';
|
import {appendActivationUniforms, appendActivationUniformsData, getActivationSnippet} from '../fuse-utils';
|
||||||
|
|
||||||
import {biasSnippet, typeSnippet} from './activation_util';
|
import {biasSnippet, typeSnippet} from './activation_util';
|
||||||
import {utilFunctions} from './conv_util';
|
import {utilFunctions} from './conv_util';
|
||||||
|
|
@ -201,10 +201,7 @@ export const createConv2DTransposeMatMulProgramInfo =
|
||||||
{type: 'int32', data: attributes.strides}, {type: 'int32', data: attributes.dilations},
|
{type: 'int32', data: attributes.strides}, {type: 'int32', data: attributes.dilations},
|
||||||
{type: 'int32', data: filterDims}, {type: 'int32', data: pads}
|
{type: 'int32', data: filterDims}, {type: 'int32', data: pads}
|
||||||
];
|
];
|
||||||
if (attributes.activation === 'Clip') {
|
appendActivationUniformsData(attributes, programUniforms);
|
||||||
programUniforms.push(
|
|
||||||
{type: 'float32', data: attributes.clipMax!}, {type: 'float32', data: attributes.clipMin!});
|
|
||||||
}
|
|
||||||
programUniforms.push(
|
programUniforms.push(
|
||||||
...createTensorShapeVariables(inputs[0].dims), ...createTensorShapeVariables(inputs[1].dims));
|
...createTensorShapeVariables(inputs[0].dims), ...createTensorShapeVariables(inputs[1].dims));
|
||||||
|
|
||||||
|
|
@ -237,9 +234,7 @@ export const createConv2DTransposeMatMulProgramInfo =
|
||||||
{name: 'filter_dims', type: 'i32', length: filterDims.length},
|
{name: 'filter_dims', type: 'i32', length: filterDims.length},
|
||||||
{name: 'pads', type: 'i32', length: pads.length}
|
{name: 'pads', type: 'i32', length: pads.length}
|
||||||
];
|
];
|
||||||
if (attributes.activation === 'Clip') {
|
appendActivationUniforms(attributes, uniforms);
|
||||||
uniforms.push({name: 'clip_max', type: 'f32'}, {name: 'clip_min', type: 'f32'});
|
|
||||||
}
|
|
||||||
return `
|
return `
|
||||||
${utilFunctions('uniforms.result_strides')}
|
${utilFunctions('uniforms.result_strides')}
|
||||||
${shaderHelper.registerUniforms(uniforms).declareVariables(...inputVariables, output)};
|
${shaderHelper.registerUniforms(uniforms).declareVariables(...inputVariables, output)};
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ import {TensorView} from '../../../tensor-view';
|
||||||
import {ShapeUtil} from '../../../util';
|
import {ShapeUtil} from '../../../util';
|
||||||
import {ProgramInfo, ProgramInputTensorInfoDependency, ProgramUniform} from '../../types';
|
import {ProgramInfo, ProgramInputTensorInfoDependency, ProgramUniform} from '../../types';
|
||||||
import {createTensorShapeVariables, getBroadcastDims, IndicesHelper, inputVariable, internalVariable, outputVariable, ShaderHelper, tensorTypeToWsglStorageType, UniformsArrayType} from '../common';
|
import {createTensorShapeVariables, getBroadcastDims, IndicesHelper, inputVariable, internalVariable, outputVariable, ShaderHelper, tensorTypeToWsglStorageType, UniformsArrayType} from '../common';
|
||||||
import {getActivationSnippet, InternalActivationAttributes} from '../fuse-utils';
|
import {appendActivationUniforms, appendActivationUniformsData, getActivationSnippet, InternalActivationAttributes} from '../fuse-utils';
|
||||||
|
|
||||||
import {typeSnippet} from './activation_util';
|
import {typeSnippet} from './activation_util';
|
||||||
|
|
||||||
|
|
@ -449,11 +449,7 @@ export const createMatmulProgramInfo =
|
||||||
const outputShapeTemp = [batchSize, dimAOuter, dimBOuter / components];
|
const outputShapeTemp = [batchSize, dimAOuter, dimBOuter / components];
|
||||||
const programUniforms: ProgramUniform[] =
|
const programUniforms: ProgramUniform[] =
|
||||||
[{type: 'int32', data: dimAOuter}, {type: 'int32', data: dimBOuter}, {type: 'int32', data: dimInner}];
|
[{type: 'int32', data: dimAOuter}, {type: 'int32', data: dimBOuter}, {type: 'int32', data: dimInner}];
|
||||||
if (activationAttributes.activation === 'Clip') {
|
appendActivationUniformsData(activationAttributes, programUniforms);
|
||||||
programUniforms.push(
|
|
||||||
{type: 'float32', data: activationAttributes.clipMax!},
|
|
||||||
{type: 'float32', data: activationAttributes.clipMin!});
|
|
||||||
}
|
|
||||||
programUniforms.push(
|
programUniforms.push(
|
||||||
...createTensorShapeVariables(outerDims), ...createTensorShapeVariables(aShapeTemp),
|
...createTensorShapeVariables(outerDims), ...createTensorShapeVariables(aShapeTemp),
|
||||||
...createTensorShapeVariables(bShapeTemp));
|
...createTensorShapeVariables(bShapeTemp));
|
||||||
|
|
@ -481,9 +477,7 @@ export const createMatmulProgramInfo =
|
||||||
}
|
}
|
||||||
const uniforms: UniformsArrayType =
|
const uniforms: UniformsArrayType =
|
||||||
[{name: 'dim_a_outer', type: 'i32'}, {name: 'dim_b_outer', type: 'i32'}, {name: 'dim_inner', type: 'i32'}];
|
[{name: 'dim_a_outer', type: 'i32'}, {name: 'dim_b_outer', type: 'i32'}, {name: 'dim_inner', type: 'i32'}];
|
||||||
if (activationAttributes.activation === 'Clip') {
|
appendActivationUniforms(activationAttributes, uniforms);
|
||||||
uniforms.push({name: 'clip_max', type: 'f32'}, {name: 'clip_min', type: 'f32'});
|
|
||||||
}
|
|
||||||
const applyActivation = getActivationSnippet(activationAttributes, output.type.value);
|
const applyActivation = getActivationSnippet(activationAttributes, output.type.value);
|
||||||
const declareFunctions = matMulReadWriteFnSource(
|
const declareFunctions = matMulReadWriteFnSource(
|
||||||
components, hasBias, applyActivation, [batchDims, A, B, output], [outerDimsA, outerDimsB, outerDims],
|
components, hasBias, applyActivation, [batchDims, A, B, output], [outerDimsA, outerDimsB, outerDims],
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import {ProgramInfo, ProgramInputTensorInfoDependency, ProgramUniform} from '../
|
||||||
|
|
||||||
import {createTensorShapeVariables, getMaxComponents, inputVariable, outputVariable, ShaderHelper, UniformsArrayType} from './common';
|
import {createTensorShapeVariables, getMaxComponents, inputVariable, outputVariable, ShaderHelper, UniformsArrayType} from './common';
|
||||||
import {calculateOutputShape, ConvAttributes} from './conv';
|
import {calculateOutputShape, ConvAttributes} from './conv';
|
||||||
import {getActivationSnippet} from './fuse-utils';
|
import {appendActivationUniforms, appendActivationUniformsData, getActivationSnippet} from './fuse-utils';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* naive grouped conv implementation, supports 1d/2d conv
|
* naive grouped conv implementation, supports 1d/2d conv
|
||||||
|
|
@ -32,10 +32,7 @@ export const createGroupedConvProgramInfo =
|
||||||
{type: 'uint32', data: [attributes.strides[0], attributes.strides[1]]},
|
{type: 'uint32', data: [attributes.strides[0], attributes.strides[1]]},
|
||||||
{type: 'uint32', data: [attributes.pads[0], attributes.pads[1]]}, {type: 'uint32', data: outputChannelsPerGroup}
|
{type: 'uint32', data: [attributes.pads[0], attributes.pads[1]]}, {type: 'uint32', data: outputChannelsPerGroup}
|
||||||
];
|
];
|
||||||
if (attributes.activation === 'Clip') {
|
appendActivationUniformsData(attributes, programUniforms);
|
||||||
programUniforms.push(
|
|
||||||
{type: 'float32', data: attributes.clipMax!}, {type: 'float32', data: attributes.clipMin!});
|
|
||||||
}
|
|
||||||
programUniforms.push(
|
programUniforms.push(
|
||||||
...createTensorShapeVariables(xShape), ...createTensorShapeVariables(wShape),
|
...createTensorShapeVariables(xShape), ...createTensorShapeVariables(wShape),
|
||||||
...createTensorShapeVariables(outputShape));
|
...createTensorShapeVariables(outputShape));
|
||||||
|
|
@ -61,9 +58,7 @@ export const createGroupedConvProgramInfo =
|
||||||
{name: 'strides', type: 'u32', length: 2}, {name: 'pads', type: 'u32', length: 2},
|
{name: 'strides', type: 'u32', length: 2}, {name: 'pads', type: 'u32', length: 2},
|
||||||
{name: 'output_channels_per_group', type: 'u32'}
|
{name: 'output_channels_per_group', type: 'u32'}
|
||||||
];
|
];
|
||||||
if (attributes.activation === 'Clip') {
|
appendActivationUniforms(attributes, uniforms);
|
||||||
uniforms.push({name: 'clip_max', type: 'f32'}, {name: 'clip_min', type: 'f32'});
|
|
||||||
}
|
|
||||||
return `
|
return `
|
||||||
${shaderHelper.registerUniforms(uniforms).declareVariables(...inputVars, output)}
|
${shaderHelper.registerUniforms(uniforms).declareVariables(...inputVars, output)}
|
||||||
|
|
||||||
|
|
@ -132,10 +127,13 @@ export const createGroupedConvVectorizeProgramInfo =
|
||||||
const outputShapeInShader = [outputShape[0], outputShape[1], outputShape[2], outputShape[3] / components];
|
const outputShapeInShader = [outputShape[0], outputShape[1], outputShape[2], outputShape[3] / components];
|
||||||
|
|
||||||
const programUniforms: ProgramUniform[] = [
|
const programUniforms: ProgramUniform[] = [
|
||||||
{type: 'uint32', data: outputSize}, {type: 'int32', data: attributes.strides},
|
{type: 'uint32', data: outputSize}, {type: 'int32', data: [attributes.strides[0], attributes.strides[1]]},
|
||||||
{type: 'int32', data: attributes.pads}, ...createTensorShapeVariables(xShape),
|
{type: 'int32', data: [attributes.pads[0], attributes.pads[1]]}
|
||||||
...createTensorShapeVariables(wShape), ...createTensorShapeVariables(outputShapeInShader)
|
|
||||||
];
|
];
|
||||||
|
appendActivationUniformsData(attributes, programUniforms);
|
||||||
|
programUniforms.push(
|
||||||
|
...createTensorShapeVariables(xShape), ...createTensorShapeVariables(wShape),
|
||||||
|
...createTensorShapeVariables(outputShapeInShader));
|
||||||
const xNumber = (outputNumber - 1) * attributes.strides[1] + wShape[1];
|
const xNumber = (outputNumber - 1) * attributes.strides[1] + wShape[1];
|
||||||
const getShaderSource = (shaderHelper: ShaderHelper) => {
|
const getShaderSource = (shaderHelper: ShaderHelper) => {
|
||||||
const output = outputVariable('output', inputs[0].dataType, outputShapeInShader.length, components);
|
const output = outputVariable('output', inputs[0].dataType, outputShapeInShader.length, components);
|
||||||
|
|
@ -147,13 +145,14 @@ export const createGroupedConvVectorizeProgramInfo =
|
||||||
inputVars.push(inputVariable('b', inputs[2].dataType, inputs[2].dims, components));
|
inputVars.push(inputVariable('b', inputs[2].dataType, inputs[2].dims, components));
|
||||||
}
|
}
|
||||||
const processBias = hasBias ? 'value += b[output_channel];' : '';
|
const processBias = hasBias ? 'value += b[output_channel];' : '';
|
||||||
|
const uniforms: UniformsArrayType = [
|
||||||
|
{name: 'output_size', type: 'u32'},
|
||||||
|
{name: 'strides', type: 'i32', length: 2},
|
||||||
|
{name: 'pads', type: 'i32', length: 2},
|
||||||
|
];
|
||||||
|
appendActivationUniforms(attributes, uniforms);
|
||||||
return `
|
return `
|
||||||
${
|
${shaderHelper.registerUniforms(uniforms).declareVariables(...inputVars, output)}
|
||||||
shaderHelper.registerUniform('output_size', 'u32')
|
|
||||||
.registerUniform('strides', 'i32', 2)
|
|
||||||
.registerUniform('pads', 'i32', 2)
|
|
||||||
.declareVariables(...inputVars, output)}
|
|
||||||
${shaderHelper.mainStart()}
|
${shaderHelper.mainStart()}
|
||||||
${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes('uniforms.output_size')}
|
${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes('uniforms.output_size')}
|
||||||
let width0 = uniforms.output_shape[3];
|
let width0 = uniforms.output_shape[3];
|
||||||
|
|
@ -173,7 +172,7 @@ export const createGroupedConvVectorizeProgramInfo =
|
||||||
// Use constant instead of uniform can give better performance for w's height/width.
|
// Use constant instead of uniform can give better performance for w's height/width.
|
||||||
for (var w_height: u32 = 0u; w_height < ${wShape[0]}; w_height++) {
|
for (var w_height: u32 = 0u; w_height < ${wShape[0]}; w_height++) {
|
||||||
let x_height = x_corner.x + i32(w_height);
|
let x_height = x_corner.x + i32(w_height);
|
||||||
if (x_height >= 0 || u32(x_height) < uniforms.x_shape[1]) {
|
if (x_height >= 0 && u32(x_height) < uniforms.x_shape[1]) {
|
||||||
for (var i = 0; i < ${xNumber}; i++) {
|
for (var i = 0; i < ${xNumber}; i++) {
|
||||||
let x_width = x_corner.y + i;
|
let x_width = x_corner.y + i;
|
||||||
if (x_width >= 0 && u32(x_width) < uniforms.x_shape[2]) {
|
if (x_width >= 0 && u32(x_width) < uniforms.x_shape[2]) {
|
||||||
|
|
@ -185,7 +184,7 @@ export const createGroupedConvVectorizeProgramInfo =
|
||||||
for (var w_width: u32 = 0u; w_width < ${wShape[1]}; w_width++) {
|
for (var w_width: u32 = 0u; w_width < ${wShape[1]}; w_width++) {
|
||||||
let w_val = ${w.get('w_height', 'w_width', '0', 'output_channel')};
|
let w_val = ${w.get('w_height', 'w_width', '0', 'output_channel')};
|
||||||
for (var i = 0u; i < ${outputNumber}u; i++) {
|
for (var i = 0u; i < ${outputNumber}u; i++) {
|
||||||
values[i] = fma(x_vals[i * ${attributes.strides[1]}u + w_width], w_val, values[i]);
|
values[i] = fma(x_vals[i * u32(uniforms.strides[1]) + w_width], w_val, values[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,16 @@
|
||||||
// Licensed under the MIT License.
|
// Licensed under the MIT License.
|
||||||
|
|
||||||
import {MAX_CLIP, MIN_CLIP} from '../../util';
|
import {MAX_CLIP, MIN_CLIP} from '../../util';
|
||||||
|
import {ProgramUniform} from '../types';
|
||||||
|
|
||||||
|
import {UniformsArrayType} from './common';
|
||||||
|
|
||||||
export interface InternalActivationAttributes {
|
export interface InternalActivationAttributes {
|
||||||
readonly activation: string;
|
readonly activation: string;
|
||||||
readonly clipMin?: number;
|
readonly clipMin?: number;
|
||||||
readonly clipMax?: number;
|
readonly clipMax?: number;
|
||||||
|
readonly alpha?: number;
|
||||||
|
readonly beta?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getActivationSnippet = (attributes: InternalActivationAttributes, valueType: string): string => {
|
export const getActivationSnippet = (attributes: InternalActivationAttributes, valueType: string): string => {
|
||||||
|
|
@ -17,17 +22,41 @@ export const getActivationSnippet = (attributes: InternalActivationAttributes, v
|
||||||
return `value = (${valueType}(1.0) / (${valueType}(1.0) + exp(-value)));`;
|
return `value = (${valueType}(1.0) / (${valueType}(1.0) + exp(-value)));`;
|
||||||
case 'Clip':
|
case 'Clip':
|
||||||
return `value = clamp(value, ${valueType}(uniforms.clip_min), ${valueType}(uniforms.clip_max));`;
|
return `value = clamp(value, ${valueType}(uniforms.clip_min), ${valueType}(uniforms.clip_max));`;
|
||||||
|
case 'HardSigmoid':
|
||||||
|
return `value = max(${valueType}(0.0), min(${valueType}(1.0), ${valueType}(uniforms.alpha) * value + ${
|
||||||
|
valueType}(uniforms.beta)));`;
|
||||||
|
case '':
|
||||||
|
return '';
|
||||||
// TODO: adding other activations that can be fused.
|
// TODO: adding other activations that can be fused.
|
||||||
default:
|
default:
|
||||||
return '';
|
throw new Error(`Unsupported activation ${attributes.activation}`);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const appendActivationUniformsData =
|
||||||
|
(attributes: InternalActivationAttributes, programUniform: ProgramUniform[]) => {
|
||||||
|
if (attributes.activation === 'Clip') {
|
||||||
|
programUniform.push({type: 'float32', data: attributes.clipMax!}, {type: 'float32', data: attributes.clipMin!});
|
||||||
|
} else if (attributes.activation === 'HardSigmoid') {
|
||||||
|
programUniform.push({type: 'float32', data: attributes.alpha!}, {type: 'float32', data: attributes.beta!});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const appendActivationUniforms = (attributes: InternalActivationAttributes, uniforms: UniformsArrayType) => {
|
||||||
|
if (attributes.activation === 'Clip') {
|
||||||
|
uniforms.push({name: 'clip_max', type: 'f32'}, {name: 'clip_min', type: 'f32'});
|
||||||
|
} else if (attributes.activation === 'HardSigmoid') {
|
||||||
|
uniforms.push({name: 'alpha', type: 'f32'}, {name: 'beta', type: 'f32'});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const parseInternalActivationAttributes =
|
export const parseInternalActivationAttributes =
|
||||||
(attributes: Record<string, unknown>|undefined): InternalActivationAttributes => {
|
(attributes: Record<string, unknown>|undefined): InternalActivationAttributes => {
|
||||||
const activation = attributes?.activation as string || '';
|
const activation = attributes?.activation as string || '';
|
||||||
|
if (activation === 'HardSigmoid') {
|
||||||
if (activation === 'Clip') {
|
const [alpha, beta] = attributes?.activation_params as [number, number] || [0.2, 0.5];
|
||||||
|
return {activation, alpha, beta};
|
||||||
|
} else if (activation === 'Clip') {
|
||||||
const [clipMin, clipMax] = attributes?.activation_params as [number, number] || [MIN_CLIP, MAX_CLIP];
|
const [clipMin, clipMax] = attributes?.activation_params as [number, number] || [MIN_CLIP, MAX_CLIP];
|
||||||
return {activation, clipMax, clipMin};
|
return {activation, clipMax, clipMin};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import {ComputeContext, ProgramInfo, ProgramUniform} from '../types';
|
||||||
|
|
||||||
import {createMatmulProgramInfo} from './3rd-party/matmul_packed_webgpu';
|
import {createMatmulProgramInfo} from './3rd-party/matmul_packed_webgpu';
|
||||||
import {createTensorShapeVariables, getBroadcastDims, getMaxComponents, IndicesHelper, inputVariable, internalVariable, outputVariable, ShaderHelper, UniformsArrayType,} from './common';
|
import {createTensorShapeVariables, getBroadcastDims, getMaxComponents, IndicesHelper, inputVariable, internalVariable, outputVariable, ShaderHelper, UniformsArrayType,} from './common';
|
||||||
import {getActivationSnippet, InternalActivationAttributes} from './fuse-utils';
|
import {appendActivationUniforms, appendActivationUniformsData, getActivationSnippet, InternalActivationAttributes} from './fuse-utils';
|
||||||
|
|
||||||
export const createNaiveMatmulProgramInfo =
|
export const createNaiveMatmulProgramInfo =
|
||||||
(inputs: readonly TensorView[], activationAttributes: InternalActivationAttributes, outputShape: readonly number[],
|
(inputs: readonly TensorView[], activationAttributes: InternalActivationAttributes, outputShape: readonly number[],
|
||||||
|
|
@ -32,11 +32,7 @@ export const createNaiveMatmulProgramInfo =
|
||||||
{type: 'uint32', data: outputSize}, {type: 'uint32', data: M}, {type: 'uint32', data: N},
|
{type: 'uint32', data: outputSize}, {type: 'uint32', data: M}, {type: 'uint32', data: N},
|
||||||
{type: 'uint32', data: K}
|
{type: 'uint32', data: K}
|
||||||
];
|
];
|
||||||
if (activationAttributes.activation === 'Clip') {
|
appendActivationUniformsData(activationAttributes, programUniforms);
|
||||||
programUniforms.push(
|
|
||||||
{type: 'float32', data: activationAttributes.clipMax!},
|
|
||||||
{type: 'float32', data: activationAttributes.clipMin!});
|
|
||||||
}
|
|
||||||
programUniforms.push(
|
programUniforms.push(
|
||||||
...createTensorShapeVariables(outerDims), ...createTensorShapeVariables(aShape),
|
...createTensorShapeVariables(outerDims), ...createTensorShapeVariables(aShape),
|
||||||
...createTensorShapeVariables(bShape));
|
...createTensorShapeVariables(bShape));
|
||||||
|
|
@ -69,9 +65,7 @@ export const createNaiveMatmulProgramInfo =
|
||||||
{name: 'output_size', type: 'u32'}, {name: 'M', type: 'u32'}, {name: 'N', type: 'u32'},
|
{name: 'output_size', type: 'u32'}, {name: 'M', type: 'u32'}, {name: 'N', type: 'u32'},
|
||||||
{name: 'K', type: 'u32'}
|
{name: 'K', type: 'u32'}
|
||||||
];
|
];
|
||||||
if (activationAttributes.activation === 'Clip') {
|
appendActivationUniforms(activationAttributes, uniforms);
|
||||||
uniforms.push({name: 'clip_max', type: 'f32'}, {name: 'clip_min', type: 'f32'});
|
|
||||||
}
|
|
||||||
|
|
||||||
const getIndices = (variable: IndicesHelper, broadCastDims: number[]) => {
|
const getIndices = (variable: IndicesHelper, broadCastDims: number[]) => {
|
||||||
const rank = variable.rank;
|
const rank = variable.rank;
|
||||||
|
|
|
||||||
|
|
@ -142,5 +142,149 @@
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "fused conv with HardSigmoid",
|
||||||
|
"operator": "FusedConv",
|
||||||
|
"attributes": [
|
||||||
|
{ "name": "activation", "data": "HardSigmoid", "type": "string" },
|
||||||
|
{ "name": "kernel_shape", "data": [2, 2], "type": "ints" },
|
||||||
|
{ "name": "activation_params", "data": [2.0, 5.0], "type": "floats" }
|
||||||
|
],
|
||||||
|
"opset": { "domain": "com.microsoft", "version": 1 },
|
||||||
|
"cases": [
|
||||||
|
{
|
||||||
|
"name": "T[0]",
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"data": [10, 20, -30, -40, -50, -60, 70, 80, 90],
|
||||||
|
"dims": [1, 1, 3, 3],
|
||||||
|
"type": "float32"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data": [1, 2, 3, 4],
|
||||||
|
"dims": [1, 1, 2, 2],
|
||||||
|
"type": "float32"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": [0, 0, 1, 1],
|
||||||
|
"dims": [1, 1, 2, 2],
|
||||||
|
"type": "float32"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "NHWC conv with HardSigmoid",
|
||||||
|
"operator": "Conv",
|
||||||
|
"attributes": [
|
||||||
|
{ "name": "activation", "data": "HardSigmoid", "type": "string" },
|
||||||
|
{ "name": "kernel_shape", "data": [2, 2], "type": "ints" },
|
||||||
|
{ "name": "activation_params", "data": [2.0, 5.0], "type": "floats" }
|
||||||
|
],
|
||||||
|
"opset": { "domain": "com.ms.internal.nhwc", "version": 1 },
|
||||||
|
"cases": [
|
||||||
|
{
|
||||||
|
"name": "T[0]",
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"data": [10, 20, -30, -40, -50, -60, 70, 80, 90],
|
||||||
|
"dims": [1, 3, 3, 1],
|
||||||
|
"type": "float32"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data": [1, 2, 3, 4],
|
||||||
|
"dims": [1, 1, 2, 2],
|
||||||
|
"type": "float32"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": [0, 0, 1, 1],
|
||||||
|
"dims": [1, 2, 2, 1],
|
||||||
|
"type": "float32"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "fused group-conv with HardSigmoid",
|
||||||
|
"operator": "FusedConv",
|
||||||
|
"attributes": [
|
||||||
|
{ "name": "activation", "data": "HardSigmoid", "type": "string" },
|
||||||
|
{ "name": "kernel_shape", "data": [2, 2], "type": "ints" },
|
||||||
|
{ "name": "group", "data": 3, "type": "int" },
|
||||||
|
{ "name": "activation_params", "data": [2.0, 5.0], "type": "floats" }
|
||||||
|
],
|
||||||
|
"opset": { "domain": "com.microsoft", "version": 1 },
|
||||||
|
"cases": [
|
||||||
|
{
|
||||||
|
"name": "T[0]",
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"data": [
|
||||||
|
0.0, 1.0, 2.0, -3.0, 4.0, -5.0, 6.0, 7.0, 8.0, -9.0, -10.0, 11.0, -12.0, 13.0, -14.0, 15.0, 16.0, 17.0,
|
||||||
|
18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0
|
||||||
|
],
|
||||||
|
"dims": [1, 3, 3, 3],
|
||||||
|
"type": "float32"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
|
||||||
|
"dims": [3, 1, 2, 2],
|
||||||
|
"type": "float32"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": [1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1],
|
||||||
|
"dims": [1, 3, 2, 2],
|
||||||
|
"type": "float32"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "NHWC group-conv with HardSigmoid",
|
||||||
|
"operator": "Conv",
|
||||||
|
"attributes": [
|
||||||
|
{ "name": "activation", "data": "HardSigmoid", "type": "string" },
|
||||||
|
{ "name": "kernel_shape", "data": [2, 2], "type": "ints" },
|
||||||
|
{ "name": "group", "data": 3, "type": "int" },
|
||||||
|
{ "name": "activation_params", "data": [2.0, 5.0], "type": "floats" }
|
||||||
|
],
|
||||||
|
"opset": { "domain": "com.ms.internal.nhwc", "version": 1 },
|
||||||
|
"cases": [
|
||||||
|
{
|
||||||
|
"name": "T[0]",
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"data": [
|
||||||
|
0.0, 1.0, 2.0, -3.0, 4.0, -5.0, 6.0, 7.0, 8.0, -9.0, -10.0, 11.0, -12.0, 13.0, -14.0, 15.0, 16.0, 17.0,
|
||||||
|
18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0
|
||||||
|
],
|
||||||
|
"dims": [1, 3, 3, 3],
|
||||||
|
"type": "float32"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
|
||||||
|
"dims": [3, 1, 2, 2],
|
||||||
|
"type": "float32"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": [0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1],
|
||||||
|
"dims": [1, 2, 2, 3],
|
||||||
|
"type": "float32"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -111,7 +111,7 @@ class ConvActivationSelector : public NodeSelector {
|
||||||
if (!graph_utils::IsSupportedOptypeVersionAndDomain(*next_node, "Relu", {6, 13, 14})) {
|
if (!graph_utils::IsSupportedOptypeVersionAndDomain(*next_node, "Relu", {6, 13, 14})) {
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
} else if (node_ep.empty() || node_ep == kCpuExecutionProvider) {
|
} else if (node_ep.empty() || node_ep == kCpuExecutionProvider || node_ep == kJsExecutionProvider) {
|
||||||
if (!is_supported_non_cuda_rocm_ep_activation(*next_node) &&
|
if (!is_supported_non_cuda_rocm_ep_activation(*next_node) &&
|
||||||
!graph_utils::IsSupportedOptypeVersionAndDomain(*next_node, "HardSigmoid", {6})) {
|
!graph_utils::IsSupportedOptypeVersionAndDomain(*next_node, "HardSigmoid", {6})) {
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue