Download src/cpu_kernels.cpp from Sariel00/Ling-3.0-tiny-RKNN: direct link, hf CLI and curl.
- Browser
- Download file 3.39 kB
-
https://huggingface.co/Sariel00/Ling-3.0-tiny-RKNN/resolve/main/src/cpu_kernels.cpp
- Command line
-
hf download hf://Sariel00/Ling-3.0-tiny-RKNN/src/cpu_kernels.cpp
-
curl -L -o cpu_kernels.cpp https://huggingface.co/Sariel00/Ling-3.0-tiny-RKNN/resolve/main/src/cpu_kernels.cpp
3.39 kB
| extern "C" float32x4_t _ZGVnN4v_expf(float32x4_t); | |
| namespace ling3 { | |
| float BFloat16ToFloat(std::uint16_t value) noexcept { | |
| std::uint32_t bits = static_cast<std::uint32_t>(value) << 16U; | |
| float result; | |
| std::memcpy(&result, &bits, sizeof(result)); | |
| return result; | |
| } | |
| std::uint16_t FloatToBFloat16(float value) noexcept { | |
| std::uint32_t bits; | |
| std::memcpy(&bits, &value, sizeof(bits)); | |
| const std::uint32_t rounded = bits + 0x7FFFU + ((bits >> 16U) & 1U); | |
| return static_cast<std::uint16_t>(rounded >> 16U); | |
| } | |
| void RmsNorm( | |
| const float * input, | |
| const float * weight, | |
| float * output, | |
| std::size_t count, | |
| float epsilon) noexcept { | |
| float sum = 0.0F; | |
| float32x4_t accum0 = vdupq_n_f32(0.0F); | |
| float32x4_t accum1 = vdupq_n_f32(0.0F); | |
| std::size_t index = 0; | |
| for (; index + 8 <= count; index += 8) { | |
| const float32x4_t a = vld1q_f32(input + index); | |
| const float32x4_t b = vld1q_f32(input + index + 4); | |
| accum0 = vfmaq_f32(accum0, a, a); | |
| accum1 = vfmaq_f32(accum1, b, b); | |
| } | |
| sum = vaddvq_f32(vaddq_f32(accum0, accum1)); | |
| for (; index < count; ++index) sum += input[index] * input[index]; | |
| for (std::size_t index = 0; index < count; ++index) sum += input[index] * input[index]; | |
| const float inverse_rms = 1.0F / std::sqrt(sum / static_cast<float>(count) + epsilon); | |
| for (std::size_t index = 0; index < count; ++index) { | |
| output[index] = input[index] * inverse_rms * weight[index]; | |
| } | |
| } | |
| void SiluMultiply(const float * gate, const float * up, float * output, std::size_t count) noexcept { | |
| std::size_t index = 0; | |
| static const bool vector_math = std::getenv("LING3_VECTOR_MATH") != nullptr; | |
| if (vector_math) { | |
| for (; index + 4 <= count; index += 4) { | |
| const auto value = vld1q_f32(gate + index); | |
| const auto divisor = vaddq_f32(vdupq_n_f32(1.0F), _ZGVnN4v_expf(vnegq_f32(value))); | |
| auto result = vdivq_f32(value, divisor); | |
| if (up) result = vmulq_f32(result, vld1q_f32(up + index)); | |
| vst1q_f32(output + index, result); | |
| } | |
| } | |
| for (; index < count; ++index) { | |
| const float value = gate[index]; | |
| const float result = value / (1.0F + std::exp(-value)); | |
| output[index] = up ? result * up[index] : result; | |
| } | |
| } | |
| void Silu(const float * input, float * output, std::size_t count) noexcept { | |
| SiluMultiply(input, nullptr, output, count); | |
| } | |
| void WeightedAccumulate(const float * input, float weight, float * output, std::size_t count) noexcept { | |
| const float32x4_t scale = vdupq_n_f32(weight); | |
| std::size_t index = 0; | |
| for (; index + 4 <= count; index += 4) { | |
| const float32x4_t source = vld1q_f32(input + index); | |
| const float32x4_t destination = vld1q_f32(output + index); | |
| vst1q_f32(output + index, vfmaq_f32(destination, source, scale)); | |
| } | |
| for (; index < count; ++index) output[index] += input[index] * weight; | |
| for (std::size_t index = 0; index < count; ++index) output[index] += input[index] * weight; | |
| } | |
| } // namespace ling3 | |