Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions include/infinicore/ops/causal_conv1d_ascend_vendor.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#pragma once

#include "../device.hpp"
#include "../graph/graph.hpp"
#include "common/op.hpp"
#include "infinicore.h"

#include <cstdint>
#include <optional>
#include <vector>

namespace infinicore::op {

// Ascend vendor fused causal-conv bridge. The vendor kernel consumes the
// vLLM-Ascend layout directly: x/out [tokens, C], weight [K, C], and state
// [pool, K - 1, C]. It also fuses SiLU and state-cache updates.
INFINICORE_GRAPH_OP_CLASS(
CausalConv1dAscendVendor,
Tensor,
Tensor,
const Tensor &,
const Tensor &,
std::optional<Tensor>,
std::vector<int64_t>,
std::vector<int64_t>,
bool,
bool);

__export Tensor causal_conv1d_ascend_vendor(
const Tensor &x,
Tensor conv_state,
const Tensor &weight,
std::optional<Tensor> bias,
std::vector<int64_t> query_start_loc,
std::vector<int64_t> cache_indices,
bool fuse_silu,
bool decode);

} // namespace infinicore::op
45 changes: 45 additions & 0 deletions include/infinicore/ops/matmul_allreduce_add_rmsnorm_ascend.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#pragma once

#include "../device.hpp"
#include "../graph/graph.hpp"
#include "common/op.hpp"
#include "infinicore.h"

#include <infiniccl.h>
#include <tuple>

namespace infinicore::op {

// vLLM-Ascend vendor bridge:
// add_out = all_reduce(input @ weight^T) + residual
// normalized = rms_norm(add_out, gamma, epsilon)
INFINICORE_GRAPH_OP_CLASS(
MatmulAllReduceAddRmsNormAscend,
Tensor,
Tensor,
const Tensor &,
const Tensor &,
const Tensor &,
const Tensor &,
infinicclComm_t,
float);

__export std::tuple<Tensor, Tensor>
matmul_allreduce_add_rmsnorm_ascend(
const Tensor &input,
const Tensor &weight,
const Tensor &residual,
const Tensor &gamma,
infinicclComm_t communicator,
float epsilon);

// vLLM-Ascend vendor bridge:
// add_out = x1 + x2
// normalized = rms_norm(add_out, gamma, epsilon)
// This directly backs RMSNorm::forward_inplace on Ascend.
__export std::tuple<Tensor, Tensor>
add_rmsnorm_ascend_vendor(
const Tensor &x1, const Tensor &x2,
const Tensor &gamma, float epsilon);

} // namespace infinicore::op
26 changes: 26 additions & 0 deletions include/infinicore/ops/matmul_allreduce_ascend.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#pragma once

#include "../device.hpp"
#include "../graph/graph.hpp"
#include "common/op.hpp"
#include "infinicore.h"

#include <infiniccl.h>

namespace infinicore::op {

// Ascend CANN MC2 bridge matching torch_npu.npu_mm_all_reduce_base:
// output = all_reduce(input @ weight_transposed).
INFINICORE_GRAPH_OP_CLASS(
MatmulAllReduceAscend,
Tensor,
const Tensor &,
const Tensor &,
infinicclComm_t);

__export Tensor matmul_allreduce_ascend(
const Tensor &input,
const Tensor &weight_transposed,
infinicclComm_t communicator);

} // namespace infinicore::op
53 changes: 50 additions & 3 deletions src/infinicore/context/allocators/pinnable_block_allocator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,53 @@ std::byte *PinnableBlockAllocator::allocate(size_t size) {

std::shared_ptr<Block> block;

// The allocator normally keeps free blocks for fast reuse. On memory-constrained
// inference servers, a workload shape change can leave enough cached blocks in
// other size classes to make a new allocation fail. Reclaim only idle,
// non-graph blocks and retry once before surfacing OOM.
auto malloc_with_reclaim = [this](void **ptr, size_t bytes) -> infiniStatus_t {
auto status = infinirtMalloc(ptr, bytes);
if (status == INFINI_STATUS_SUCCESS && *ptr != nullptr) {
return status;
}

size_t reclaimed_blocks = 0;
size_t reclaimed_bytes = 0;
for (auto &cls : size_classes_) {
for (auto it = cls.free_blocks.begin(); it != cls.free_blocks.end();) {
if (!(*it)->frozen && !(*it)->in_use) {
reclaimed_bytes += (*it)->size;
++reclaimed_blocks;
INFINICORE_CHECK_ERROR(infinirtFree((*it)->ptr));
all_blocks_.erase((*it)->ptr);
it = cls.free_blocks.erase(it);
} else {
++it;
}
}
}
for (auto it = large_blocks_.begin(); it != large_blocks_.end();) {
if (!(*it)->frozen && !(*it)->in_use) {
reclaimed_bytes += (*it)->size;
++reclaimed_blocks;
INFINICORE_CHECK_ERROR(infinirtFree((*it)->ptr));
all_blocks_.erase((*it)->ptr);
it = large_blocks_.erase(it);
} else {
++it;
}
}
if (reclaimed_blocks > 0) {
spdlog::warn("Device allocation of {} bytes failed; reclaimed {} idle blocks ({} bytes) and retrying",
bytes, reclaimed_blocks, reclaimed_bytes);
}
status = infinirtMalloc(ptr, bytes);
if (status == INFINI_STATUS_SUCCESS && *ptr == nullptr) {
return INFINI_STATUS_INTERNAL_ERROR;
}
return status;
};

// 1. Try size-class allocation for small/medium
for (auto &cls : size_classes_) {
if (size <= cls.block_size) {
Expand Down Expand Up @@ -74,7 +121,7 @@ std::byte *PinnableBlockAllocator::allocate(size_t size) {
block->in_use = true;
block->use_count = 1;

INFINICORE_CHECK_ERROR(infinirtMalloc(&block->ptr, block->size));
INFINICORE_CHECK_ERROR(malloc_with_reclaim(&block->ptr, block->size));

all_blocks_[block->ptr] = block;
return reinterpret_cast<std::byte *>(block->ptr);
Expand All @@ -101,7 +148,7 @@ std::byte *PinnableBlockAllocator::allocate(size_t size) {
block->in_use = true;
block->use_count = 1;

INFINICORE_CHECK_ERROR(infinirtMalloc(&block->ptr, block->size));
INFINICORE_CHECK_ERROR(malloc_with_reclaim(&block->ptr, block->size));

large_blocks_.push_back(block);
all_blocks_[block->ptr] = block;
Expand Down Expand Up @@ -166,7 +213,7 @@ void PinnableBlockAllocator::trim() {
// Free non-frozen size-class blocks
for (auto &cls : size_classes_) {
for (auto it = cls.free_blocks.begin(); it != cls.free_blocks.end();) {
if (!(*it)->frozen) {
if (!(*it)->frozen && !(*it)->in_use) {
INFINICORE_CHECK_ERROR(infinirtFree((*it)->ptr));
all_blocks_.erase((*it)->ptr);
it = cls.free_blocks.erase(it);
Expand Down
20 changes: 20 additions & 0 deletions src/infinicore/nn/rmsnorm.cc
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
#include "infinicore/nn/rmsnorm.hpp"
#include "infinicore/ops.hpp"
#ifdef ENABLE_ASCEND_API
#include "infinicore/ops/matmul_allreduce_add_rmsnorm_ascend.hpp"
#endif
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <stdexcept>
#include <tuple>

namespace infinicore::nn {

Expand All @@ -26,6 +32,20 @@ void RMSNorm::forward_inplace(Tensor &x, Tensor &residual) const {
residual = x;
x = op::rms_norm(x, weight_, static_cast<float>(eps_));
} else {
#ifdef ENABLE_ASCEND_API
static const bool ascend_vendor_enabled = []() {
const char *value = std::getenv(
"INFINICORE_ASCEND_ADD_RMSNORM_VENDOR");
return value == nullptr || std::strcmp(value, "0") != 0;
}();
if (device_.getType() == Device::Type::ASCEND
&& ascend_vendor_enabled) {
std::tie(x, residual) = op::add_rmsnorm_ascend_vendor(
x, residual, weight_,
static_cast<float>(eps_));
return;
}
#endif
if (device_.getType() == Device::Type::CPU
|| device_.getType() == Device::Type::NVIDIA
|| device_.getType() == Device::Type::ILUVATAR
Expand Down
Loading
Loading