- 前两个
for
循环在每个像素上迭代,其输出彼此不变;因此,我们可以在这两个for
循环上并行化。第三个for
循环计算特定像素的最终值,本质上是递归的。 - 阿姆达尔定律没有考虑在 GPU 和主机之间传输内存所需的时间。
- 512 x 512 相当于 262144 像素。这意味着第一 GPU 一次只能计算一半像素的输出,而第二 GPU 一次可以计算所有像素;这意味着第二个 GPU 的速度大约是第一个 GPU 的两倍。第三个 GPU 有足够多的内核一次计算所有像素,但正如我们在问题 1 中看到的,额外的内核在这里对我们没有用处。因此,对于这个问题,第二个和第三个 GPU 将同样快。
- 根据阿姆达尔定律,一般将某段代码指定为可并行的一个问题是,如果处理器数量N非常大,则这段代码的计算时间将接近于 0。从上一个问题可以看出,情况并非如此。
- 首先,持续使用时间可能会很麻烦,而且可能不会关注程序的瓶颈。其次,分析器可以从 Python 的角度告诉您所有代码的精确计算时间,因此您可以判断操作系统的某些库函数或后台活动是否出错,而不是代码。
- 不支持,CUDA 仅支持 Nvidia GPU,不支持 Intel HD 或 AMD Radeon
- 本书仅使用 Python 2.7 示例
- 设备管理器
lspci
free
.run
- 对
- 主机/设备之间的内存传输以及编译时间。
- 您可以,但这取决于您的 GPU 和 CPU 设置。
- 使用 C
?
运算符执行逐点和减少操作。 - 如果
gpuarray
对象超出范围,则调用其析构函数,该析构函数将自动释放(释放)它在 GPU 上表示的内存。 ReductionKernel
可能会执行多余的操作,这可能是必要的,具体取决于底层 GPU 代码的结构。中性元件将确保这些多余操作不会改变任何值。- 我们应该将
neutral
设置为有符号 32 位整数的最小可能值。
-
试试看。
-
所有线程不会同时在 GPU 上运行。就像操作系统中的 CPU 在任务之间切换一样,GPU 的各个内核在内核的不同线程之间切换。
-
O(n/640logn),即 O(n logn)。
-
试试看。
-
实际上,在 CUDA 纯块级中没有内部网格级同步(使用
__syncthreads).
时,我们必须将单个块以上的任何内容与主机同步。 -
朴素:129 个加法运算。工作效率:62 个加法运算。
-
同样,如果我们需要在一个大的块网格上进行同步,我们不能使用
__syncthreads
。如果我们在主机上同步,我们也可以在每次迭代中启动更少的线程,从而为其他操作释放更多的资源。 -
在简单并行求和的情况下,我们可能只处理少量数据点,这些数据点应等于或小于 GPU 内核总数,这可能适合块的最大大小(1032);因为单个块可以在内部同步,所以我们应该这样做。只有当数据点的数量远远大于 GPU 上可用内核的数量时,我们才应该使用工作效率高的算法。
- 两者的性能都有所提高;随着线程数量的增加,GPU 在这两种情况下都达到了峰值利用率,从而减少了通过使用流所获得的收益。
- 是的,您可以异步启动任意数量的内核,并将它们与
cudaDeviceSynchronize
同步。 - 打开你的文本编辑器,试试看!
- 高标准偏差意味着 GPU 的使用不均衡,在某些点上超过 GPU,而在其他点上利用不足。较低的标准偏差意味着所有已启动的操作通常运行平稳。
- 我主机处理的并发线程通常比 GPU 少得多。二,。每个线程都需要自己的 CUDA 上下文。GPU 可能会被过多的上下文淹没,因为每个上下文都有自己的内存空间,并且必须处理自己加载的可执行代码。
- 内存分配在 CUDA 中自动同步。
lockstep
属性仅适用于大小为 32 或更小的单个块。在这里,两个区块将在没有任何lockstep
的情况下适当分开。- 同样的事情也会发生在这里。这个 64 线程块实际上会被分成两个 32 线程的扭曲。
- Nvprof 可以计算单个内核的启动时间、GPU 利用率和流使用率;任何主机端探查器都只能看到正在启动的 CUDA 主机功能。
- Printf 通常更容易用于具有相对较短的内联内核的小规模项目。如果您编写了一个包含数千行的非常复杂的 CUDA 内核,那么您可能希望使用 IDE 逐行调试内核。
- 这会告诉 CUDA 我们要使用哪个 GPU。
cudaDeviceSynchronize
将确保相互依赖的内核启动和 mem 拷贝确实同步,并且在所有必要操作完成之前不会启动。
- SBLAH 以 S 开头,因此此函数使用 32 位实浮点。ZBLEH 以 Z 开头,这意味着它使用 128 位复数浮点。
- 提示:设置
trans = cublas._CUBLAS_OP['T']
- 提示:使用 Scikit CUDA 包装器包装 dot 产品,
skcuda.cublas.cublasSdot
- 提示:基于上一个问题的答案。
- 您可以将 cuBLAS 操作放入 CUDA 流中,并使用此流中的事件对象来精确测量 GPU 上的计算时间。
- 因为输入对 cuFFT 来说很复杂,所以它将以 NumPy 计算所有值。
- 暗边是由于图像周围的零缓冲造成的。这可以通过在其边缘镜像图像而不是使用零缓冲区来缓解。
- 试试看。(事实上比你想象的更准确。)
- 一个应用:高斯分布可用于向样本中添加
white noise
,以增强机器学习中的数据集。 - 不,因为它们来自不同的种子,如果我们将它们连接在一起,这些列表可能具有很强的相关性。如果我们计划将它们连接在一起,我们应该使用同一种子的子序列。
- 试试看。
- 提示:请记住,矩阵乘法可以看作是一系列矩阵向量乘法,而矩阵向量乘法可以看作是一系列点积。
Operator()
用于定义实际功能。
- 一个问题可能是我们没有将培训投入标准化。另一个原因可能是训练率太高。
- 在训练速率很小的情况下,一组权重可能收敛得很慢,或者根本不收敛。
- 较大的训练率可能导致一组权重与特定批次值或该训练集过度匹配。此外,它还可能导致第一个问题中的数值溢出/下溢。
- 乙状结肠。
- Softmax。
- 更多更新。
- 只有 EXE 文件具有主机功能,但 PTX 和 EXE 都将包含 GPU 代码。
cuCtxDestory
。printf
具有任意输入参数。(尝试查找printf
原型。)- 使用 Ctypes
c_void_p
对象。 - 这将允许我们从 Ctypes 链接到具有原始名称的函数。
- CUDA 自动同步设备/主机之间的设备内存分配和 memcopies。
atomicExch
是线程安全的事实并不保证所有线程都会同时执行此函数(事实并非如此,因为网格中的不同块可以在不同的时间执行)。- 大小为 100 的块将在多个扭曲上执行,除非我们使用
__syncthreads
,否则这些扭曲不会在块内同步。因此,atomicExch
可以被多次调用。 - 由于默认情况下以 lockstep 方式执行扭曲,并且大小为 32 或更小的块使用单个扭曲执行,
__syncthreads
将是不必要的。 - 我们在 warp 中使用了一个幼稚的并行求和,但在其他方面,我们使用
atomicAdd
进行的求和与使用串行求和一样多。虽然 CUDA 会自动并行许多此类atomicAdd
调用,但我们可以通过实现工作效率高的并行求和来减少所需atomicAdd
调用的总数。 - 肯定是
sum_ker
。很明显,PyCUDA 的 sum 没有使用与我们相同的硬件技巧,因为我们的 sum 在更小的阵列上性能更好,但通过将大小扩展到更大的阵列,PyCUDA 版本更好的唯一原因是它执行的加法操作更少。
- 两个例子:DNA 分析和物理模拟。
- 两个例子:OpenACC、Numba。
- TPU 仅用于机器学习操作,缺少渲染图形所需的组件。
- 以太网。