Skip to content

Conversation

@smk2007
Copy link
Member

@smk2007 smk2007 commented Feb 9, 2021

Add LearningModelBuilder to WinML Experimental Namespace along with various Audio operators

This PR includes the following features:

  1. A bunch of experimental Signal Processing Operators to enable Audio scenarios.

    • DFT
    • IDFT
    • STFT
    • HannWindow
    • HammingWindow
    • BlackmanWindow
    • MelWeightMatrix
      These operators are included behind the build flag --experimental, and are part of the com.microsoft.experimental domain.
  2. Add experimental ModelBuilding classes to Microsoft.AI.MachineLearning.Expermental namespace

    • LearningModelBuilder
    • LearningModelOperator
    • LearningModelOperatorSet
    • LearningModelInputs
    • LearningModelOutputs
      These classes enable dynamic onnx model building useful for featurization and testing.

Comment on lines +57 to +132
static bool is_power_of_2(size_t size) {
unsigned n_bits = 0;
while (size != 0) {
n_bits += size & 1;
size = size >> 1;
}
return n_bits == 1;
}

static const unsigned char BitReverseTable256[] =
{
0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF};

template <unsigned TSignificantBits>
uint32_t bit_reverse(uint32_t num) {
uint32_t rev = (BitReverseTable256[num & 0xff] << 24) |
(BitReverseTable256[(num >> 8) & 0xff] << 16) |
(BitReverseTable256[(num >> 16) & 0xff] << 8) |
(BitReverseTable256[(num >> 24) & 0xff]);
return static_cast<uint32_t>(((uint64_t)rev) >> (32 - TSignificantBits));
}

template <typename T>
static inline T bit_reverse(T num, unsigned significant_bits) {
switch (significant_bits) {
case 0: return static_cast<T>(bit_reverse<0>(static_cast<uint32_t>(num)));
case 1: return static_cast<T>(bit_reverse<1>(static_cast<uint32_t>(num)));
case 2: return static_cast<T>(bit_reverse<2>(static_cast<uint32_t>(num)));
case 3: return static_cast<T>(bit_reverse<3>(static_cast<uint32_t>(num)));
case 4: return static_cast<T>(bit_reverse<4>(static_cast<uint32_t>(num)));
case 5: return static_cast<T>(bit_reverse<5>(static_cast<uint32_t>(num)));
case 6: return static_cast<T>(bit_reverse<6>(static_cast<uint32_t>(num)));
case 7: return static_cast<T>(bit_reverse<7>(static_cast<uint32_t>(num)));
case 8: return static_cast<T>(bit_reverse<8>(static_cast<uint32_t>(num)));
case 9: return static_cast<T>(bit_reverse<9>(static_cast<uint32_t>(num)));
case 10: return static_cast<T>(bit_reverse<10>(static_cast<uint32_t>(num)));
case 11: return static_cast<T>(bit_reverse<11>(static_cast<uint32_t>(num)));
case 12: return static_cast<T>(bit_reverse<12>(static_cast<uint32_t>(num)));
case 13: return static_cast<T>(bit_reverse<13>(static_cast<uint32_t>(num)));
case 14: return static_cast<T>(bit_reverse<14>(static_cast<uint32_t>(num)));
case 15: return static_cast<T>(bit_reverse<15>(static_cast<uint32_t>(num)));
case 16: return static_cast<T>(bit_reverse<16>(static_cast<uint32_t>(num)));
case 17: return static_cast<T>(bit_reverse<17>(static_cast<uint32_t>(num)));
case 18: return static_cast<T>(bit_reverse<18>(static_cast<uint32_t>(num)));
case 19: return static_cast<T>(bit_reverse<19>(static_cast<uint32_t>(num)));
case 20: return static_cast<T>(bit_reverse<20>(static_cast<uint32_t>(num)));
case 21: return static_cast<T>(bit_reverse<21>(static_cast<uint32_t>(num)));
case 22: return static_cast<T>(bit_reverse<22>(static_cast<uint32_t>(num)));
case 23: return static_cast<T>(bit_reverse<23>(static_cast<uint32_t>(num)));
case 24: return static_cast<T>(bit_reverse<24>(static_cast<uint32_t>(num)));
case 25: return static_cast<T>(bit_reverse<25>(static_cast<uint32_t>(num)));
case 26: return static_cast<T>(bit_reverse<26>(static_cast<uint32_t>(num)));
case 27: return static_cast<T>(bit_reverse<27>(static_cast<uint32_t>(num)));
case 28: return static_cast<T>(bit_reverse<28>(static_cast<uint32_t>(num)));
case 29: return static_cast<T>(bit_reverse<29>(static_cast<uint32_t>(num)));
case 30: return static_cast<T>(bit_reverse<30>(static_cast<uint32_t>(num)));
case 31: return static_cast<T>(bit_reverse<31>(static_cast<uint32_t>(num)));
case 32: return static_cast<T>(bit_reverse<32>(static_cast<uint32_t>(num)));
default: ORT_THROW("Unsupported bit size.");
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using compiler intrinsics might be worth it

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which intrinsic?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

popcnt for population count (number of 1 bits), rbit to reverse bits in ARM. For bit reverse in x86 there's fancy ways using SIMD that are reportedly >5 times faster than the lookup table solution, like https://stackoverflow.com/a/24058332/1390418 and https://stackoverflow.com/a/46318399/1390418, but it's much trickier to implement


template <typename T>
static T get_scalar_value_from_tensor(const Tensor* tensor) {
ORT_ENFORCE(tensor->Shape().Size() == 1, "ratio input should have a single value.");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this error message descriptive enough to know which operator is wrong and how to fix it?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed to Tensor input should have single value.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error message can be better here.

@smk2007 smk2007 merged commit 87cb6fd into master Feb 12, 2021
@smk2007 smk2007 deleted the user/sheilk/training-explorations branch February 12, 2021 22:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants