Repository: ggerganov/llama.cpp
File: ggml/src/ggml-cann/ggml-cann.cpp (C++)

Code before:
    if (ggml_is_quantized(tensor->type)) {
        // Initialize padding to 0 to avoid possible NaN values
        size_t original_size = ggml_nbytes(tensor);
        size_t padded_size =
            ggml_backend_buft_get_alloc_size(buffer->buft, tensor);

        if (padded_size > original_size && tensor->view_src == nullptr) {
            size_t memset_size = padded_size - original_size;
            ACL_CHECK(aclrtMemset((char*)tensor->data + original_size,
                                  memset_size, 0, memset_size));
        }
    }
    return GGML_STATUS_SUCCESS;
}

// ND to NZ Workspace Cache Management. Thread-safety: Not guaranteed
class NzWorkspace {
public:
    // Constructor: initialize with no allocated buffer
    NzWorkspace() : ptr_(nullptr), allocated_(0) {}

    // Reset workspace to uninitialized state:
    // - Free allocated device memory (if any)
    // - Clear internal pointer and size
    // Equivalent to release_nz_workspace(device) in old version
    void init() {
        if (ptr_) {
            aclrtFree(ptr_);
            ptr_ = nullptr;
            allocated_ = 0;
        }
    }

    // Allocate or reallocate the workspace buffer:
    // - If requested size > currently allocated size:
    //   * Free the old buffer (if any)
    //   * Allocate a new buffer with requested size on device
    // - If requested size <= currently allocated size:
    //   * Do nothing (reuse existing buffer)
    // Equivalent to relloc_nz_workspace(device, new_size) in old version
    void realloc(size_t new_size) {
        if (new_size > allocated_) {
            init();
            ACL_CHECK(aclrtMalloc(&ptr_, new_size, ACL_MEM_MALLOC_HUGE_FIRST));
            allocated_ = new_size;
        }
    }

    // Return raw device pointer (may be nullptr if not allocated)
    // Equivalent to get_nz_workspace(device) in old version
    void* get() const { return ptr_; }

Review comment (performance):
Use constructor instead. and add a clear fucntion to free cached memory.

Code after:
    if (ggml_is_quantized(tensor->type)) {
        // Initialize padding to 0 to avoid possible NaN values
        size_t original_size = ggml_nbytes(tensor);
        size_t padded_size =
            ggml_backend_buft_get_alloc_size(buffer->buft, tensor);

        if (padded_size > original_size && tensor->view_src == nullptr) {
            size_t memset_size = padded_size - original_size;
            ACL_CHECK(aclrtMemset((char*)tensor->data + original_size,
                                  memset_size, 0, memset_size));
        }
    }
    return GGML_STATUS_SUCCESS;
}

/**
 * @brief Workspace for caching NZ buffers per device.
 *
 * This struct manages a device buffer used in NZ computations. It supports
 * allocation, reallocation, and clearing of cached memory. The struct is
 * designed to be used with a global array, one per device.
 */
struct ggml_cann_nz_workspace {
    void*  ptr;       // Pointer to allocated device buffer
    size_t allocated; // Size of currently allocated buffer in bytes

    /**
     * @brief Constructor. Initializes the workspace with no allocated memory.
     */
    ggml_cann_nz_workspace() : ptr(nullptr), allocated(0) {}

    /**
     * @brief Free cached memory and reset the workspace.
     *
     * If a buffer has been allocated, this function releases it using
     * aclrtFree and resets internal state.
     */
    void clear() {
        if (ptr) {
            ACL_CHECK(aclrtFree(ptr));
            ptr = nullptr;
            allocated = 0;
        }
    }

    /**
     * @brief Allocate or reallocate the workspace buffer.
     *
     * If the requested size is larger than the currently allocated size,
     * the old buffer will be freed and a new buffer of the requested size
     * will be allocated on the device.