CANN内存管理与资源优化

引言

内存管理是深度学习推理性能的关键因素之一。CANN提供了丰富的内存管理机制和优化策略,通过合理的内存分配、复用和优化,可以显著提升推理性能,降低内存占用,提高资源利用率。

本文将深入介绍CANN的内存管理机制和资源优化方法,帮助开发者构建高效的内存管理方案。

相关链接:

一、CANN内存架构

1.1 内存层次结构

CANN的内存系统采用多层次架构,不同层次的内存具有不同的访问速度和容量。

python 复制代码
def memory_hierarchy_demo():
    """CANN内存层次结构"""
    print("CANN内存层次结构")
    print("=" * 50)

    print("\n1. Host内存(主机内存)")
    print("   - 位置: CPU端")
    print("   - 速度: 相对较慢")
    print("   - 容量: 大(数十GB)")
    print("   - 用途: 数据存储、预处理")

    print("\n2. Device内存(设备内存)")
    print("   - 位置: 加速器端")
    print("   - 速度: 快")
    print("   - 容量: 中等(数GB到数十GB)")
    print("   - 用途: 模型存储、计算数据")

    print("\n3. Unified Memory(统一内存)")
    print("   - 位置: Host和Device共享")
    print("   - 速度: 中等")
    print("   - 容量: 大")
    print("   - 用途: 简化编程,自动迁移")

    print("\n4. 缓存(Cache)")
    print("   - 位置: 硬件内部")
    print("   - 速度: 最快")
    print("   - 容量: 小(KB到MB)")
    print("   - 用途: 热点数据缓存")

    print("=" * 50)

memory_hierarchy_demo()
1.2 内存访问模式
python 复制代码
def memory_access_patterns():
    """内存访问模式"""
    print("内存访问模式")
    print("=" * 50)

    patterns = [
        "1. 顺序访问",
        "   - 特点: 连续访问内存",
        "   - 性能: 高(缓存命中率高)",
        "   - 适用: 矩阵运算、卷积操作",
        "",
        "2. 随机访问",
        "   - 特点: 非连续访问内存",
        "   - 性能: 低(缓存命中率低)",
        "   - 适用: 稀疏操作、索引访问",
        "",
        "3. 流式访问",
        "   - 特点: 单向连续访问",
        "   - 性能: 高(预取效果好)",
        "   - 适用: 数据加载、结果输出",
        "",
        "4. 重访问",
        "   - 特点: 重复访问同一数据",
        "   - 性能: 取决于缓存策略",
        "   - 适用: 迭代计算、累积操作"
    ]

    for pattern in patterns:
        print(pattern)

    print("\n优化建议:")
    print("- 尽量使用顺序访问")
    print("- 提高数据局部性")
    print("- 减少随机访问")
    print("- 利用缓存机制")

    print("=" * 50)

memory_access_patterns()

二、内存分配与释放

2.1 基础内存操作
python 复制代码
import acl
import numpy as np

class CANNMemoryManager:
    """CANN内存管理器"""
    def __init__(self, device_id=0):
        self.device_id = device_id
        ret = acl.init()
        ret = acl.rt.set_device(device_id)

    def malloc_host(self, size):
        """分配Host内存"""
        ptr, ret = acl.rt.malloc_host(size)
        if ret != 0:
            raise RuntimeError(f"Host内存分配失败: {ret}")
        return ptr

    def malloc_device(self, size):
        """分配Device内存"""
        ptr, ret = acl.rt.malloc(size, 0)
        if ret != 0:
            raise RuntimeError(f"Device内存分配失败: {ret}")
        return ptr

    def free_host(self, ptr):
        """释放Host内存"""
        ret = acl.rt.free_host(ptr)
        if ret != 0:
            raise RuntimeError(f"Host内存释放失败: {ret}")

    def free_device(self, ptr):
        """释放Device内存"""
        ret = acl.rt.free(ptr)
        if ret != 0:
            raise RuntimeError(f"Device内存释放失败: {ret}")

    def memcpy_h2d(self, device_ptr, host_ptr, size):
        """Host到Device数据传输"""
        ret = acl.rt.memcpy(device_ptr, size,
                           host_ptr, size,
                           acl.rt.MEMCPY_HOST_TO_DEVICE)
        if ret != 0:
            raise RuntimeError(f"数据传输失败: {ret}")

    def memcpy_d2h(self, host_ptr, device_ptr, size):
        """Device到Host数据传输"""
        ret = acl.rt.memcpy(host_ptr, size,
                           device_ptr, size,
                           acl.rt.MEMCPY_DEVICE_TO_HOST)
        if ret != 0:
            raise RuntimeError(f"数据传输失败: {ret}")

# 使用示例
mem_manager = CANNMemoryManager(device_id=0)

# 分配内存
data = np.random.rand(1024, 1024).astype(np.float32)
host_ptr = mem_manager.malloc_host(data.nbytes)
device_ptr = mem_manager.malloc_device(data.nbytes)

# 数据传输
mem_manager.memcpy_h2d(device_ptr, host_ptr, data.nbytes)

# ... 执行计算 ...

# 释放内存
mem_manager.free_host(host_ptr)
mem_manager.free_device(device_ptr)
2.2 内存对齐
python 复制代码
def aligned_memory_allocation():
    """内存对齐分配"""
    print("内存对齐优化")
    print("=" * 50)

    print("\n1. 为什么需要内存对齐:")
    reasons = [
        "- 硬件要求: 某些硬件要求内存对齐",
        "- 访问效率: 对齐的内存访问更快",
        "- 原子操作: 某些操作需要内存对齐",
        "- DMA传输: DMA通常需要对齐的内存"
    ]

    for reason in reasons:
        print(f"   {reason}")

    print("\n2. 常见对齐要求:")
    alignments = [
        "- 32字节对齐: SIMD操作",
        "- 64字节对齐: 缓存行大小",
        "- 128字节对齐: 某些加速器",
        "- 512字节对齐: 大块数据传输"
    ]

    for align in alignments:
        print(f"   {align}")

    print("\n3. CANN内存对齐:")
    print("- acl.rt.malloc()自动对齐")
    print("- 通常对齐到32或64字节")
    print("- 确保硬件最优访问")

    print("=" * 50)

aligned_memory_allocation()

三、内存复用策略

3.1 内存池实现
python 复制代码
import threading

class MemoryPool:
    """内存池"""
    def __init__(self, device_id=0):
        self.device_id = device_id
        self.pools = {}  # {size: [(ptr, used_timestamp), ...]}
        self.lock = threading.Lock()
        self.max_pool_size = 1000  # 最大池大小

    def allocate(self, size):
        """从池中分配内存"""
        with self.lock:
            # 尝试从池中获取
            pool_key = self._get_pool_key(size)
            if pool_key in self.pools and self.pools[pool_key]:
                ptr, _ = self.pools[pool_key].pop()
                return ptr

            # 池中没有,分配新的
            ptr, ret = acl.rt.malloc(size, 0)
            if ret != 0:
                raise RuntimeError(f"内存分配失败: {ret}")

            return ptr

    def deallocate(self, ptr, size):
        """归还内存到池中"""
        with self.lock:
            pool_key = self._get_pool_key(size)

            if pool_key not in self.pools:
                self.pools[pool_key] = []

            # 检查池大小
            if len(self.pools[pool_key]) >= self.max_pool_size:
                # 池已满,直接释放
                acl.rt.free(ptr)
            else:
                # 归还到池中
                self.pools[pool_key].append((ptr, time.time()))

    def _get_pool_key(self, size):
        """获取池的键值(按大小分组)"""
        # 将大小对齐到最近的2的幂
        aligned_size = 1
        while aligned_size < size:
            aligned_size <<= 1
        return aligned_size

    def clear(self):
        """清空内存池"""
        with self.lock:
            for pool_key, blocks in self.pools.items():
                for ptr, _ in blocks:
                    acl.rt.free(ptr)
            self.pools.clear()

# 使用示例
memory_pool = MemoryPool(device_id=0)

# 分配内存
data = np.random.rand(1024, 1024).astype(np.float32)
ptr1 = memory_pool.allocate(data.nbytes)
ptr2 = memory_pool.allocate(data.nbytes)

# 使用内存...

# 归还内存
memory_pool.deallocate(ptr1, data.nbytes)
memory_pool.deallocate(ptr2, data.nbytes)

# 清空池
memory_pool.clear()
3.2 中间结果复用
python 复制代码
class IntermediateBufferPool:
    """中间结果缓冲池"""
    def __init__(self, device_id=0):
        self.device_id = device_id
        self.buffers = {}  # {shape: [(ptr, ref_count), ...]}
        self.lock = threading.Lock()

    def get_buffer(self, shape, dtype=np.float32):
        """获取缓冲区"""
        size = np.prod(shape) * np.dtype(dtype).itemsize
        buffer_key = (shape, dtype)

        with self.lock:
            if buffer_key in self.buffers and self.buffers[buffer_key]:
                ptr, ref_count = self.buffers[buffer_key].pop()
                # 增加引用计数
                return ptr, ref_count + 1

            # 分配新缓冲区
            ptr, ret = acl.rt.malloc(size, 0)
            if ret != 0:
                raise RuntimeError(f"缓冲区分配失败: {ret}")

            return ptr, 1

    def release_buffer(self, ptr, shape, dtype=np.float32, ref_count=1):
        """释放缓冲区"""
        buffer_key = (shape, dtype)

        with self.lock:
            if ref_count > 1:
                # 仍有引用,减计数
                self.buffers[buffer_key].append((ptr, ref_count - 1))
            else:
                # 没有引用,归还到池中
                if buffer_key not in self.buffers:
                    self.buffers[buffer_key] = []
                self.buffers[buffer_key].append((ptr, 0))

    def clear(self):
        """清空缓冲池"""
        with self.lock:
            for buffer_key, buffers in self.buffers.items():
                for ptr, _ in buffers:
                    acl.rt.free(ptr)
            self.buffers.clear()

四、内存优化技术

4.1 零拷贝优化
python 复制代码
def zero_copy_demo():
    """零拷贝优化"""
    print("零拷贝优化技术")
    print("=" * 50)

    print("\n1. 什么是零拷贝:")
    print("   - 直接访问数据,无需复制")
    print("   - 减少内存带宽消耗")
    print("   - 降低CPU开销")

    print("\n2. CANN零拷贝技术:")
    techniques = [
        "a) Device直接访问",
        "   - 在Device端处理数据",
        "   - 避免Host和Device间传输",
        "   - 使用acl.rt.malloc()直接分配",

        "b) Pinned Memory",
        "   - 使用页锁定内存",
        "   - DMA直接传输",
        "   - 使用acl.rt.malloc_host()",

        "c) Shared Memory",
        "   - Host和Device共享内存",
        "   - 减少数据复制",
        "   - 适合小数据频繁交互"
    ]

    for tech in techniques:
        print(f"\n{tech}")

    print("\n3. 使用示例:")
    code = """
# 使用Pinned Memory实现零拷贝
host_ptr = acl.rt.malloc_host(size)
device_ptr = acl.rt.malloc(size, 0)

# DMA直接传输,无需CPU拷贝
acl.rt.memcpy(device_ptr, size, host_ptr, size,
              acl.rt.MEMCPY_HOST_TO_DEVICE)
"""
    print(code)

    print("\n4. 性能提升:")
    print("- 减少CPU负载")
    print("- 提高传输速度")
    print("- 降低功耗")

    print("=" * 50)

zero_copy_demo()
4.2 内存预分配
python 复制代码
class PreallocatedMemoryManager:
    """预分配内存管理器"""
    def __init__(self, device_id=0, sizes=None):
        self.device_id = device_id
        self.memory_blocks = {}  # {size: [ptr1, ptr2, ...]}

        # 预分配内存
        if sizes:
            for size in sizes:
                count = max(10, size // (1024 * 1024))  # 每MB至少10个块
                for _ in range(count):
                    ptr, ret = acl.rt.malloc(size, 0)
                    if ret == 0:
                        if size not in self.memory_blocks:
                            self.memory_blocks[size] = []
                        self.memory_blocks[size].append(ptr)

    def allocate(self, size):
        """分配内存"""
        # 找到合适的预分配块
        for pool_size in sorted(self.memory_blocks.keys()):
            if pool_size >= size:
                if self.memory_blocks[pool_size]:
                    ptr = self.memory_blocks[pool_size].pop()
                    return ptr

        # 没有合适的预分配块,分配新的
        ptr, ret = acl.rt.malloc(size, 0)
        if ret != 0:
            raise RuntimeError(f"内存分配失败: {ret}")
        return ptr

    def deallocate(self, ptr, size):
        """释放内存"""
        # 检查是否有对应大小的池
        if size in self.memory_blocks:
            self.memory_blocks[size].append(ptr)
        else:
            acl.rt.free(ptr)

    def get_memory_info(self):
        """获取内存信息"""
        info = {}
        for size, blocks in self.memory_blocks.items():
            info[size] = {
                'total_blocks': len(blocks),
                'available_blocks': len(blocks),
                'total_size': size * len(blocks)
            }
        return info

# 使用示例
sizes = [1024, 4096, 16384, 65536, 262144, 1048576]  # 常用大小
mem_manager = PreallocatedMemoryManager(device_id=0, sizes=sizes)

# 快速分配内存
ptr1 = mem_manager.allocate(1024)
ptr2 = mem_manager.allocate(5000)  # 使用4096的块

# 释放内存
mem_manager.deallocate(ptr1, 1024)
mem_manager.deallocate(ptr2, 5000)

# 查看内存信息
print(mem_manager.get_memory_info())

五、动态内存管理

5.1 动态Shape内存管理
python 复制代码
class DynamicShapeMemoryManager:
    """动态Shape内存管理器"""
    def __init__(self, device_id=0):
        self.device_id = device_id
        self.shape_history = {}  # {shape_tuple: count}
        self.memory_cache = {}  # {shape: ptr}
        self.lock = threading.Lock()

    def allocate_for_shape(self, shape, dtype=np.float32):
        """为特定Shape分配内存"""
        size = np.prod(shape) * np.dtype(dtype).itemsize
        shape_key = tuple(shape)

        with self.lock:
            # 记录Shape使用频率
            if shape_key not in self.shape_history:
                self.shape_history[shape_key] = 0
            self.shape_history[shape_key] += 1

            # 检查是否有缓存的内存
            if shape_key in self.memory_cache:
                return self.memory_cache[shape_key]

            # 分配新内存
            ptr, ret = acl.rt.malloc(size, 0)
            if ret != 0:
                raise RuntimeError(f"内存分配失败: {ret}")

            # 缓存常用Shape的内存
            if self.shape_history[shape_key] > 5:  # 使用超过5次才缓存
                self.memory_cache[shape_key] = ptr

            return ptr

    def get_shape_statistics(self):
        """获取Shape统计信息"""
        with self.lock:
            sorted_shapes = sorted(
                self.shape_history.items(),
                key=lambda x: x[1],
                reverse=True
            )
            return sorted_shapes[:10]  # 返回前10个常用Shape

    def clear_cache(self):
        """清空缓存"""
        with self.lock:
            for ptr in self.memory_cache.values():
                acl.rt.free(ptr)
            self.memory_cache.clear()

# 使用示例
shape_manager = DynamicShapeMemoryManager(device_id=0)

# 处理不同Shape的输入
shapes = [(1, 3, 224, 224), (1, 3, 320, 320), (1, 3, 640, 640)]
for shape in shapes:
    ptr = shape_manager.allocate_for_shape(shape)
    # 使用内存...
    print(f"为Shape {shape} 分配内存")

# 查看常用Shape
print("常用Shape统计:")
print(shape_manager.get_shape_statistics())
5.2 内存碎片整理
python 复制代码
def memory_defragmentation():
    """内存碎片整理"""
    print("内存碎片整理")
    print("=" * 50)

    print("\n1. 内存碎片问题:")
    problems = [
        "   - 频繁分配释放导致碎片",
        "   - 降低内存利用率",
        "   - 影响分配性能",
        "   - 可能导致分配失败"
    ]

    for problem in problems:
        print(problem)

    print("\n2. 碎片整理策略:")
    strategies = [
        "   a) 定期整理",
        "   - 设置整理周期",
        "   - 在低负载时执行",
        "   - 释放并重新分配",

        "   b) 内存池",
        "   - 预分配大块内存",
        "   - 内部管理分配",
        "   - 减少外部碎片",

        "   c) 分配策略",
        "   - 使用固定大小块",
        "   - 对齐分配",
        "   - 避免频繁释放"
    ]

    for strategy in strategies:
        print(strategy)

    print("\n3. 实施建议:")
    recommendations = [
        "   - 使用内存池减少碎片",
        "   - 定期监控内存使用",
        "   - 在应用启动时预分配",
        "   - 避免频繁的小块分配"
    ]

    for rec in recommendations:
        print(rec)

    print("=" * 50)

memory_defragmentation()

六、内存监控与调试

6.1 内存使用监控
python 复制代码
class MemoryMonitor:
    """内存监控器"""
    def __init__(self, device_id=0):
        self.device_id = device_id
        self.allocations = {}  # {ptr: {'size': size, 'timestamp': time, 'tag': tag}}
        self.peak_memory = 0
        self.current_memory = 0
        self.lock = threading.Lock()

    def record_allocation(self, ptr, size, tag=""):
        """记录内存分配"""
        with self.lock:
            self.allocations[ptr] = {
                'size': size,
                'timestamp': time.time(),
                'tag': tag
            }
            self.current_memory += size
            self.peak_memory = max(self.peak_memory, self.current_memory)

    def record_deallocation(self, ptr):
        """记录内存释放"""
        with self.lock:
            if ptr in self.allocations:
                size = self.allocations[ptr]['size']
                del self.allocations[ptr]
                self.current_memory -= size

    def get_memory_info(self):
        """获取内存信息"""
        with self.lock:
            return {
                'current_memory': self.current_memory,
                'peak_memory': self.peak_memory,
                'allocation_count': len(self.allocations),
                'allocations': list(self.allocations.values())
            }

    def print_memory_summary(self):
        """打印内存摘要"""
        info = self.get_memory_info()
        print("\n内存使用摘要:")
        print(f"  当前内存: {info['current_memory'] / 1024**2:.2f} MB")
        print(f"  峰值内存: {info['peak_memory'] / 1024**2:.2f} MB")
        print(f"  分配数量: {info['allocation_count']}")

        if info['allocation_count'] > 0:
            print("\n  最大的10个分配:")
            sorted_allocs = sorted(
                info['allocations'],
                key=lambda x: x['size'],
                reverse=True
            )[:10]
            for alloc in sorted_allocs:
                print(f"    {alloc['size'] / 1024**2:.2f} MB - {alloc['tag']}")

# 使用示例
memory_monitor = MemoryMonitor(device_id=0)

# 分配内存时记录
ptr1 = acl.rt.malloc(1024*1024, 0)
memory_monitor.record_allocation(ptr1, 1024*1024, tag="buffer1")

ptr2 = acl.rt.malloc(2048*1024, 0)
memory_monitor.record_allocation(ptr2, 2048*1024, tag="buffer2")

# 释放内存时记录
memory_monitor.record_deallocation(ptr1)
acl.rt.free(ptr1)

# 查看内存信息
memory_monitor.print_memory_summary()
6.2 内存泄漏检测
python 复制代码
class MemoryLeakDetector:
    """内存泄漏检测器"""
    def __init__(self):
        self.allocations = {}
        self.leak_threshold = 10  # 分配次数阈值

    def track_allocation(self, ptr, size, location=""):
        """跟踪内存分配"""
        stack = traceback.extract_stack()
        caller = str(stack[-2]) if len(stack) > 1 else ""

        if ptr not in self.allocations:
            self.allocations[ptr] = {
                'size': size,
                'alloc_count': 0,
                'free_count': 0,
                'locations': [],
                'last_alloc_time': time.time()
            }

        alloc_info = self.allocations[ptr]
        alloc_info['alloc_count'] += 1
        alloc_info['last_alloc_time'] = time.time()
        if location:
            alloc_info['locations'].append(location)
        if caller:
            alloc_info['locations'].append(caller)

    def track_deallocation(self, ptr):
        """跟踪内存释放"""
        if ptr in self.allocations:
            self.allocations[ptr]['free_count'] += 1

    def detect_leaks(self):
        """检测内存泄漏"""
        leaks = []

        for ptr, info in self.allocations.items():
            # 检查分配和释放次数不平衡
            if info['alloc_count'] > info['free_count'] + self.leak_threshold:
                leaks.append({
                    'ptr': ptr,
                    'size': info['size'],
                    'alloc_count': info['alloc_count'],
                    'free_count': info['free_count'],
                    'leak_count': info['alloc_count'] - info['free_count'],
                    'locations': info['locations']
                })

        return leaks

    def print_leak_report(self):
        """打印泄漏报告"""
        leaks = self.detect_leaks()

        if not leaks:
            print("未检测到内存泄漏")
            return

        print(f"\n检测到 {len(leaks)} 处潜在的内存泄漏:")
        for i, leak in enumerate(leaks, 1):
            print(f"\n泄漏 #{i}:")
            print(f"  指针: 0x{leak['ptr']:X}")
            print(f"  大小: {leak['size']} bytes")
            print(f"  分配次数: {leak['alloc_count']}")
            print(f"  释放次数: {leak['free_count']}")
            print(f"  泄漏次数: {leak['leak_count']}")
            print(f"  分配位置:")
            for loc in leak['locations'][-5:]:  # 显示最近5个位置
                print(f"    {loc}")

# 使用示例
leak_detector = MemoryLeakDetector()

# 分配内存时跟踪
ptr = acl.rt.malloc(1024*1024, 0)
leak_detector.track_allocation(ptr, 1024*1024, location="main:100")

# 检测泄漏
leak_detector.print_leak_report()

七、内存优化最佳实践

7.1 优化建议
python 复制代码
def memory_optimization_best_practices():
    """内存优化最佳实践"""
    print("内存优化最佳实践")
    print("=" * 50)

    practices = [
        "1. 预分配内存",
        "   - 在应用启动时分配所需内存",
        "   - 避免运行时频繁分配",
        "   - 使用内存池管理",

        "",
        "2. 及时释放",
        "   - 不再使用的内存立即释放",
        "   - 避免内存泄漏",
        "   - 使用RAII模式",

        "",
        "3. 复用内存",
        "   - 中间结果复用",
        "   - 模型参数共享",
        "   - 批处理内存复用",

        "",
        "4. 对齐分配",
        "   - 按照硬件要求对齐",
        "   - 提升访问效率",
        "   - 避免性能损失",

        "",
        "5. 监控使用",
        "   - 实时监控内存使用",
        "   - 记录峰值内存",
        "   - 检测内存泄漏",

        "",
        "6. 合理规划",
        "   - 估算内存需求",
        "   - 留出余量",
        "   - 分配策略优化"
    ]

    for practice in practices:
        print(practice)

    print("=" * 50)

memory_optimization_best_practices()
7.2 常见问题
python 复制代码
def common_memory_issues():
    """常见内存问题及解决方案"""
    print("常见内存问题及解决方案")
    print("=" * 50)

    issues = [
        "问题1: 内存不足",
        "   原因: Batch Size过大,模型参数多",
        "   解决: 减小Batch Size,使用量化,模型压缩",

        "",
        "问题2: 内存泄漏",
        "   原因: 分配后未释放,引用计数错误",
        "   解决: 使用内存监控,及时释放,检查代码",

        "",
        "问题3: 内存碎片",
        "   原因: 频繁分配释放,大小不一",
        "   解决: 使用内存池,预分配,定期整理",

        "",
        "问题4: 性能低下",
        "   原因: 频繁传输,未对齐,缓存未命中",
        "   解决: 减少传输,内存对齐,优化访问模式",

        "",
        "问题5: 分配失败",
        "   原因: 内存不足,碎片严重",
        "   解决: 释放内存,整理碎片,增加内存"
    ]

    for issue in issues:
        print(issue)

    print("=" * 50)

common_memory_issues()

总结

本文详细介绍了CANN内存管理与资源优化的各个方面,包括:

  • CANN内存架构和访问模式
  • 内存分配与释放
  • 内存复用策略
  • 内存优化技术
  • 动态内存管理
  • 内存监控与调试
  • 内存优化最佳实践

通过合理的内存管理和优化,可以显著提升CANN应用的性能,降低资源消耗,提高系统稳定性。建议开发者根据具体应用场景,选择合适的内存管理策略,并持续监控和优化内存使用。

相关链接:

相关推荐
愚公搬代码10 小时前
【愚公系列】《AI短视频创作一本通》016-AI短视频的生成(AI短视频运镜方法)
人工智能·音视频
极新10 小时前
智启新篇,智创未来,“2026智造新IP:AI驱动品牌增长新周期”峰会暨北京电子商务协会第五届第三次会员代表大会成功举办
人工智能·网络协议·tcp/ip
island131410 小时前
CANN GE(图引擎)深度解析:计算图优化管线、内存静态规划与异构任务的 Stream 调度机制
开发语言·人工智能·深度学习·神经网络
艾莉丝努力练剑10 小时前
深度学习视觉任务:如何基于ops-cv定制图像预处理流程
人工智能·深度学习
禁默10 小时前
大模型推理的“氮气加速系统”:全景解读 Ascend Transformer Boost (ATB)
人工智能·深度学习·transformer·cann
User_芊芊君子10 小时前
CANN大模型加速核心ops-transformer全面解析:Transformer架构算子的高性能实现与优化
人工智能·深度学习·transformer
格林威10 小时前
Baumer相机玻璃制品裂纹自动检测:提高透明材质检测精度的 6 个关键步骤,附 OpenCV+Halcon 实战代码!
人工智能·opencv·视觉检测·材质·工业相机·sdk开发·堡盟相机
点云SLAM10 小时前
Concentrate 英文单词学习
人工智能·英文单词学习·雅思备考·concentrate·集中·浓缩 / 集中物
哈__10 小时前
CANN轻量化开发实战:快速上手与多场景适配
人工智能