我最近被问到一段代码来"就地"对数组进行抽取/下采样.这个"抽取"函数采用一个int数组,并在索引i
处的数组中的偶数索引处存储一个条目i/2
.它为数组中的所有条目执行此操作.
这会将原始数组中所有偶数索引条目移动到数组的前半部分.然后阵列的其余部分可被初始化为0总的结果是,保留了原始阵列中的所有偶数索引条目(通过将它们移动到第一半部分)的阵列,并且所述阵列的第二半被0.这显然用于在信号处理中对信号进行下采样.
代码看起来像这样:
void decimate (vector<int>& a) {
int sz = a.size();
for (int i =0; i < sz; i++) {
if (i%2 == 0) {
a[i/2] = a[i];
}
}
for (int i =(sz-1)/2; i < sz; i++) a[i] = 0;
}
Run Code Online (Sandbox Code Playgroud)
在建议将某些变量保留在寄存器中的基本改进之后,我找不到任何进一步优化它的方法,但不确定是否无法完成.
有没有办法可以优化循环中的内存访问模式,以获得更好的缓存性能? 或者任何其他方法来优化将阵列压缩/下采样到上半部分的主要复制操作?(例如,通过支持它的平台进行矢量化)
for (int i =0; i < sz; i++) {
if (i%2 == 0) {
a[i/2] = a[i];
}
}
Run Code Online (Sandbox Code Playgroud)
是否有任何循环变换(例如平铺/条带挖掘)可以为这种抽取循环带来高效的代码?
编辑:在下面的答案中提出了几种不同的方法,似乎利用memset/fill或指针算法来提高速度效率.这个问题主要集中在是否有明确定义的循环变换可以显着改善局部性或缓存未命中(例如,如果它是一个带有两个循环的循环嵌套,可能会考虑循环平铺以优化缓存未命中)
我一直试图理解(但惨败)图像(具有高度、宽度、通道)的卷积是如何在软件中实现的。
我听人们说他们的卷积实现是使用 GEMM 完成的,或者使用“直接卷积”完成的,或者使用 1x1 内核完成的。
我发现它非常令人困惑,无法理解到处都有描述的如此多不同的方式 - 我以为我将像pytorch conv2d这样的典型卷积理解为图像上的数学运算,但是当有人说他们做 conv2d 时,他们是什么意思使用以下方法之一?
对于使用 GEMM 进行卷积,我根据本文的理解是,每个输入图像和滤波器都使用im2col
和im2row
操作转换为二维矩阵,然后将这两个矩阵简单地进行矩阵相乘。
3d 输入图像(高度、宽度、输入通道)转换为 2d 矩阵,4d 内核(输出通道、输入通道、内核高度、内核宽度)转换为 2d 矩阵。或者“基于 GEMM 的卷积实现”还有其他含义吗?如果这就是它的意思,那么它与“使用 1x1 内核进行卷积”有何不同?
tiling convolution matrix-multiplication conv-neural-network tensorflow
我理解应用于图像时的卷积滤波器(例如,具有 3 个输入通道的 224x224 图像由 56 个 5x5 转换的总共 56 个滤波器转换为具有 56 个输出通道的 224x224 图像)。关键是有 56 个不同的滤波器,每个滤波器的权重为 5x5x3,最终生成输出图像 224x224, 56(逗号后面的术语是输出通道)。
\n\n但我似乎无法理解conv1d
过滤器在字符序列的 seq2seq 模型中如何工作。我正在查看的模型之一https://arxiv.org/pdf/1712.05884.pdf有一个“ post-net 层由 512 个形状为 5\xc3\x971 的滤波器组成”,在频谱图帧 80-d 上运行(意味着帧中有80个不同的浮点值),过滤的结果是512维的帧。
我不明白in_channels, out_channels
pytorch conv1d 定义中的含义,就像在图像中一样,我可以轻松理解通道内/通道外的含义,但对于 80 个浮点值帧的序列,我不知所措。在上面这样的 seq2seq 模型的上下文中它们意味着什么?
对 80 个浮点值进行 512、5x1 过滤器如何生成 512 个浮点值?**
当对 80 个浮点值进行操作时,5x1 过滤器是否只会产生 80 个浮点值(通过在这 80 个值中一次取 5 个连续值)?这 512 个过滤器总共有多少权重?**
在 pytorch 中打印时的图层显示为:
\n\n(conv): Conv1d(80, 512, kernel_size=(5,), …
Run Code Online (Sandbox Code Playgroud) 我试图在https://pytorch.org/hub/nvidia_deeplearningexamples_tacotron2/下载以下模型
import torch
tacotron2 = torch.hub.load('nvidia/DeepLearningExamples:torchhub', 'nvidia_tacotron2')
Run Code Online (Sandbox Code Playgroud)
我收到了:
>>> import torch
>>> tacotron2 = torch.hub.load('nvidia/DeepLearningExamples:torchhub', 'nvidia_tacotron2')
Using cache found in .cache\torch\hub\nvidia_DeepLearningExamples_torchhub
...
File "Anaconda3\envs\env3_pytorch\lib\site-packages\torch\serialization.py", line 79, in validate_cuda_device
raise RuntimeError('Attempting to deserialize object on a CUDA '
RuntimeError: Attempting to deserialize object on a CUDA device but torch.cuda.is_available() is False. If you are running on a CPU-only machine, please use torch.load with map_location='cpu' to map your storages to the CPU.
Run Code Online (Sandbox Code Playgroud)
所以我使用了以下 with map_location='cpu'
,但仍然得到相同的错误。
>>> tacotron2 = torch.hub.load('nvidia/DeepLearningExamples:torchhub', …
Run Code Online (Sandbox Code Playgroud) 这个简单的自定义比较器用于tuple<int, int, int>
下面的示例测试的类型崩溃。我检查cout
了cmp
比较器中的语句,每次调用cmp
都会得到一个返回值,所以它不像元组 t1 和 t2 中的值是垃圾。
知道为什么会崩溃吗?这个非常简单的自定义比较器有什么问题吗?
class Solution {
public:
vector<int> assignBikes(vector<vector<int>>& ws, vector<vector<int>>& bs) {
int n = ws.size(), m = bs.size();
vector<tuple<int, int, int>> dist;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
int d = abs(ws[i][0]-bs[j][0]) + abs(ws[i][1]-bs[j][1]);
dist.push_back(make_tuple(d, i, j));
}
}
sort(dist.begin(), dist.end(), cmp());
}
struct cmp {
bool operator() (tuple<int, int, int>& …
Run Code Online (Sandbox Code Playgroud) c++ ×2
convolution ×2
pytorch ×2
caching ×1
comparator ×1
conda ×1
loops ×1
lstm ×1
performance ×1
seq2seq ×1
sorting ×1
std ×1
tensorflow ×1
tiling ×1