❶ 学习编程有必要做笔记吗
我感觉用不着写笔记, 如果真的想记录一些做仿自己遇到的问题, 不如在csdn或者其他地方开个博客, 这样也便于保存, 每天基胡戚可以把学习心得写到博客里。 见证自己的成长。搏陵
最最重要的, 学习编程要多实践, 学到的每个例子最好都能自己领会,然后不看教程上机编一变, 提高会很快
❷ cuda编程笔记(一):首次尝试
在深入了解GPU底层前,建议直接尝试一个编程小例子,学习正反馈更强。一个典型的CUDA程序实现流程如下:
首先,内存管理是关键,使用`cudaMalloc`函数类似C语言的`malloc`,还有其他内存管理函数如`cudaMemcpy`。`cudaMemcpy`是同步执行的,这意味着CPU会等待内存复制操作完成后再继续执行,这通常会占据大量时间,耗时的不是计算,而是内存拷贝。了解`cudaMemcpy`的`kind`参数,用于确定复制的方向,一般有几种选项。
此外,函数的返回值是`cudaError_t`枚举类型,成功时返回`cudaSuccess`,失败时返回其他错误代码,可以使用`cudaGetErrorString`将错误代码转换为可读的错误消息。
在GPU中,内存可以分为全局内存和共享内存。全局内存类似于CPU的系统内存,共享内存则类似CPU的缓存。GPU的共享内存可以被编程直接控制,而CPU的缓存则不可以。这两者的具体区别将在后续的文章中详细介绍。
线程管理在GPU中非常重要,GPU用于管理大量线程。首先,了解线程由进程产生,一个GPU进程由CPU创建,这代表了一个核函数kernel的执行。在GPU上,可以同时运行多个GPU进程或核函数。
软件层面的层次化管理包括线程网格Grid、线程块Block、线程thread。网格和块都是三维的组织结构。在定义核函数时,需要使用`__global__`修饰符。CUDA提供了三种限定符,用于控制核函数的执行方式。
调用核函数时,使用`<< >>>`配置运算符传递核函数的执行参数,包括网格形状、块形状、共享内存大小和执行流。其中网格和块都是`dim3`类型,表示三个维度,可以通过其x、y、z字段获取。
理解`threadIdx`和`blockIdx`在核函数中的作用是至关重要的。`threadIdx`和`blockIdx`是核函数中需要预初始化的内置变量,用于线程索引的建立和数组索引的获取。在核函数中,线程通常会执行数组操作,如数组加法。
核函数预初始化了两个内置变量:`blockDim`和`gridDim`,分别表示线程块的维度范围和线程格的维度范围。当有多个GPU设备时,根据`multiProcessorCount`来选择最优的GPU设备。
在实现数组加法的CUDA代码中,确保数据从CPU内存复制到GPU内存,执行核函数进行操作,并将结果从GPU内存复制回CPU内存。理解代码流程是至关重要的。
最后,核函数是异步执行的,可以通过`cudaDeviceSynchronize()`方法显示同步。了解如何查询和管理GPU设备信息,如使用CUDA运行时API函数查询设备属性和数量,以便在运行时优化设备配置。
❸ 学习编程|Spring源码深度解析 读书笔记 第4章:bean的加载
在Spring框架中,bean的加载过程是一个精细且有序的过程。首先,当需要加载bean时,Spring会尝试通过转换beanName来识别目标对象,可能涉及到别名或FactoryBean的识别。
加载过程分为几步:从缓存查找单例,Spring容器内单例只创建一次,若缓存中无数据,会尝试从singletonFactories寻找。接着是bean的实例化,从缓存获取原始状态后,可能需要进一步处理以符合预期状态。
原型模式的依赖检查是单例模式特有的,用来避免循环依赖问题。然后,如果缓存中无数据,会检查parentBeanFactory,递归加载配置。BeanDefinition会被转换为RootBeanDefinition,合并父类属性,确保依赖的正确初始化。
Spring根据不同的scope策略创建bean,如singleton、prototype等。类型转换是后续步骤,可能将返回的bean转换为所需的类型。FactoryBean的使用提供了灵活的实例化逻辑,用户自定义创建bean的过程。
当bean为FactoryBean时,getBean()方法代理了FactoryBean的getObject(),允许通过不同的方式配置bean。缓存中获取单例时,会执行循环依赖检测和性能优化。最后,通过ObjectFactory实例singletonFactory定义bean的完整加载逻辑,包括回调方法用于处理单例创建前后的状态。