我正在尝试学习《金属》以进行科学编程。我尝试创建一个进行形态学膨胀的简单内核。我面临的问题是,每次我在图像上调用CancellationToken
时,内存似乎都会增加几个KB。
我通过在for循环中运行dilate
方法进行10000次迭代来验证内存泄漏,并观察Xcode的调试导航器中分配的内存从16MB增加到17MB。
您在代码中看到的任何内容都会导致内存泄漏吗?如果有帮助,我还将该项目推到了Github。
dilate
我的内核看起来像这样:
class MorphologyIOS : public Morphology
{
public:
MorphologyIOS(
const uint kernel,
const uint width,
const uint height
) {
device_ = MTLCreateSystemDefaultDevice();
kernelSize_ = kernel;
buffer_ = [device_ newBufferWithBytes:&kernelSize_ length:4 options:MTLStorageModeShared];
library_ = [device_ newDefaultLibrary];
commandQueue_ = [device_ newCommandQueue];
identityFunction_ = [library_ newFunctionWithName:@"identity"];
MTLTextureDescriptor* readDesc = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormat::MTLPixelFormatR8Uint
width:width height:height mipmapped:false];
MTLTextureDescriptor* writeDesc = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormat::MTLPixelFormatR8Uint
width:width height:height mipmapped:false];
[writeDesc setUsage:MTLTextureUsageShaderWrite];
inTexture_ = [device_ newTextureWithDescriptor:readDesc];
outTexture_ = [device_ newTextureWithDescriptor:writeDesc];
entireImage_ = MTLRegionMake2D(0, 0, width, height);
pipelineState_ = [device_ newComputePipelineStateWithFunction:identityFunction_ error:NULL];
}
virtual ~MorphologyIOS() override {}
virtual std::shared_ptr<unsigned char> dilate(
const std::shared_ptr<unsigned char>& inImage
) override {
void* result = malloc(outTexture_.width * outTexture_.height);
std::shared_ptr<unsigned char> outImage;
@autoreleasepool
{
commandBuffer_ = [commandQueue_ commandBuffer];
commandEncoder_ = [commandBuffer_ computeCommandEncoder];
[commandEncoder_ setComputePipelineState:pipelineState_];
[inTexture_ replaceRegion:entireImage_ mipmapLevel:0 withBytes:inImage.get() bytesPerRow:outTexture_.width];
[commandEncoder_ setTexture:inTexture_ atIndex:0];
[commandEncoder_ setTexture:outTexture_ atIndex:1];
[commandEncoder_ setBuffer:buffer_ offset:0 atIndex:0];
MTLSize threadGroupCount = MTLSizeMake(10, 10, 1);
MTLSize threadGroups = MTLSizeMake(inTexture_.width / threadGroupCount.width,
inTexture_.height / threadGroupCount.height, 1);
[commandEncoder_ dispatchThreadgroups:threadGroups threadsPerThreadgroup:threadGroupCount];
[commandEncoder_ endEncoding];
[commandBuffer_ commit];
[commandBuffer_ waitUntilCompleted];
[outTexture_ getBytes:result bytesPerRow:outTexture_.width fromRegion:entireImage_ mipmapLevel:0];
outImage.reset(reinterpret_cast<unsigned char*>(result));
}
return outImage;
}
private:
id<MTLDevice> device_;
uint kernelSize_;
id<MTLBuffer> buffer_;
id<MTLLibrary> library_;
id<MTLComputePipelineState> pipelineState_;
id<MTLCommandQueue> commandQueue_;
id<MTLFunction> identityFunction_;
id<MTLCommandBuffer> commandBuffer_;
id<MTLComputeCommandEncoder> commandEncoder_;
id<MTLTexture> inTexture_;
id<MTLTexture> outTexture_;
MTLRegion entireImage_;
};
答案 0 :(得分:0)
这并不是一个错误,因为它是捕获/验证层的人工产物,代表您进行一些簿记。由于它不会在实际使用中发生,因此可能不必担心。