相关疑难解决方法(0)

在C++中转置矩阵的最快方法是什么?

我有一个矩阵(相对较大),我需要转置.例如假设我的矩阵是

a b c d e f
g h i j k l
m n o p q r 
Run Code Online (Sandbox Code Playgroud)

我希望结果如下:

a g m
b h n
c I o
d j p
e k q
f l r
Run Code Online (Sandbox Code Playgroud)

最快的方法是什么?

c++ algorithm transpose matrix

75
推荐指数
3
解决办法
9万
查看次数

如何使用SIMD指令转置16x16矩阵?

我目前正在编写一些针对英特尔即将推出的AVX-512 SIMD指令的代码,该指令支持512位操作.

现在假设有一个由16个SIMD寄存器表示的矩阵,每个寄存器包含16个32位整数(对应一行),如何用纯SIMD指令转置矩阵?

已经有解决方案分别用SSE和AVX2转置4x4或8x8矩阵.但我无法弄清楚如何使用AVX-512将其扩展到16x16.

有任何想法吗?

assembly intel simd matrix avx512

13
推荐指数
2
解决办法
4722
查看次数

使用AVX而不是AVX2,通过许多64位位掩码分别计算每个位的位置

(相关:如何在Sandy Bridge上的一系列int中快速将位计数到单独的bin中?是对此的早期复制,带有一些不同的答案。编者注:这里的答案可能更好。

同样,是类似问题的AVX2版本,整行位的许多bin比一个宽得多uint64_t改进列填充计数算法


我正在C中的一个项目中,我需要经历数千万个掩码(ulong类型(64位)),并target基于一个简单规则更新64个短整数(uint16)的数组(称为):

// for any given mask, do the following loop
for (i = 0; i < 64; i++) {
    if (mask & (1ull << i)) {
        target[i]++
    }
}
Run Code Online (Sandbox Code Playgroud)

问题是我需要在数以百万计的蒙版上执行上述循环,并且我需要在不到一秒钟的时间内完成。想知道是否有任何方法可以加快它的速度,例如使用某种表示上述循环的特殊汇编指令。

目前,我在ubuntu 14.04(i7-2670QM,支持AVX,而不是AVX2)上使用gcc 4.8.4来编译和运行以下代码,大约需要2秒钟。很想让它在200ms以下运行。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <sys/stat.h>

double getTS() {
    struct timeval tv;
    gettimeofday(&tv, NULL);
    return tv.tv_sec + tv.tv_usec / 1000000.0;
}
unsigned int target[64];

int main(int argc, char *argv[]) {
    int i, …
Run Code Online (Sandbox Code Playgroud)

c optimization x86 x86-64 simd

13
推荐指数
4
解决办法
635
查看次数

将向量的向量转换为具有相反存储顺序的单个连续向量的更快方法

std::vector<std::vector<double>>正在尝试尽快将其转换为单个连续向量。我的向量的形状大致为4000 x 50

问题是,有时我的输出向量需要以列为主的连续顺序(仅将2d输入向量的内部向量连接起来),有时我的输出向量需要以行为主的连续顺序,实际上需要转置。

我发现,朴素的for循环对于转换为以列为主的向量非常快:

auto to_dense_column_major_naive(std::vector<std::vector<double>> const & vec)
    -> std::vector<double>
{
    auto n_col = vec.size();
    auto n_row = vec[0].size();
    std::vector<double> out_vec(n_col * n_row);
    for (size_t i = 0; i < n_col; ++i)
        for (size_t j = 0; j < n_row; ++j)
            out_vec[i * n_row + j] = vec[i][j];
    return out_vec;
}
Run Code Online (Sandbox Code Playgroud)

但是显然,由于所有的高速缓存未命中,因此类似的方法对于逐行转换非常慢。因此,对于逐行转换,我认为提高缓存局部性的阻止策略可能是我最好的选择:

auto to_dense_row_major_blocking(std::vector<std::vector<double>> const & vec)
    -> std::vector<double>
{
    auto n_col = vec.size();
    auto n_row = vec[0].size();
    std::vector<double> out_vec(n_col * n_row);
    size_t block_side …
Run Code Online (Sandbox Code Playgroud)

c++ performance caching vector

12
推荐指数
1
解决办法
381
查看次数

使用SSE,AVX和OpenMP进行快速内存转置

我需要一个快速的内存转置算法,用于C/C++中的高斯卷积函数.我现在做的是

convolute_1D
transpose
convolute_1D
transpose
Run Code Online (Sandbox Code Playgroud)

事实证明,使用这种方法,滤波器的大小必须很大(或大于我的预期),或者转置需要比卷积更长的时间(例如,对于1920x1080矩阵,卷积与转置的时间相同,滤波器大小为35 ).我正在使用的当前转置算法使用循环阻塞/平铺以及SSE和OpenMP.我尝试过使用AVX的版本,但速度并不快.关于如何加快速度的任何建议?

inline void transpose4x4_SSE(float *A, float *B, const int lda, const int ldb) {
    __m128 row1 = _mm_load_ps(&A[0*lda]);
    __m128 row2 = _mm_load_ps(&A[1*lda]);
    __m128 row3 = _mm_load_ps(&A[2*lda]);
    __m128 row4 = _mm_load_ps(&A[3*lda]);
     _MM_TRANSPOSE4_PS(row1, row2, row3, row4);
     _mm_store_ps(&B[0*ldb], row1);
     _mm_store_ps(&B[1*ldb], row2);
     _mm_store_ps(&B[2*ldb], row3);
     _mm_store_ps(&B[3*ldb], row4);
}
//block_size = 16 works best
inline void transpose_block_SSE4x4(float *A, float *B, const int n, const int m, const int lda, const int ldb ,const int block_size) {
    #pragma omp parallel for …
Run Code Online (Sandbox Code Playgroud)

optimization transpose sse openmp avx

11
推荐指数
1
解决办法
5392
查看次数

一个更好的8x8字节矩阵转置与SSE?

我发现这个职位,说明如何进行转一个8x8矩阵的字节24点的操作,和几个卷轴后有代码实现转置.但是,这种方法没有利用我们可以阻止 8x8转置为4个4x4转置的事实,并且每个转换只能在一个shuffle指令中完成(这篇文章是参考文献).所以我推出了这个解决方案:

__m128i transpose4x4mask = _mm_set_epi8(15, 11, 7, 3, 14, 10, 6, 2, 13,  9, 5, 1, 12,  8, 4, 0);
__m128i shuffle8x8Mask = _mm_setr_epi8(0, 1, 2, 3, 8, 9, 10, 11, 4,  5, 6, 7, 12,  13, 14, 15);

void TransposeBlock8x8(uint8_t *src, uint8_t *dst, int srcStride, int dstStride) {
    __m128i load0 = _mm_set_epi64x(*(uint64_t*)(src + 1 * srcStride), *(uint64_t*)(src + 0 * srcStride));
    __m128i load1 = _mm_set_epi64x(*(uint64_t*)(src + 3 * srcStride), *(uint64_t*)(src + …
Run Code Online (Sandbox Code Playgroud)

c optimization sse simd matrix

11
推荐指数
1
解决办法
1273
查看次数

在SSE2/SSSE3上转换8个16位元素寄存器

(我是SSE/asm的新手,如果这显而易见或多余则道歉)

是否有更好的方法来转换包含16位值的8个SSE寄存器,而不是执行24个unpck [lh] ps和8/16 + shuffle以及使用8个额外的寄存器?(注意最多使用SSSE 3指令,Intel Merom,又称SSE4缺少BLEND*.)

假设你有寄存器v [0-7]并使用t0-t7作为辅助寄存器.在伪内在函数代码中:

/* Phase 1: process lower parts of the registers */
/* Level 1: work first part of the vectors */
/*   v[0]  A0 A1 A2 A3 A4 A5 A6 A7
**   v[1]  B0 B1 B2 B3 B4 B5 B6 B7
**   v[2]  C0 C1 C2 C3 C4 C5 C6 C7
**   v[3]  D0 D1 D2 D3 D4 D5 D6 D7
**   v[4]  E0 E1 E2 E3 E4 E5 E6 E7 …
Run Code Online (Sandbox Code Playgroud)

x86 assembly sse simd matrix

6
推荐指数
2
解决办法
3310
查看次数

如何用SSE3实现签名功能?

1)有没有办法使用具有以下特征的SSE3(无SSE4)有效地实现符号功能

  • 输入是一个浮点向量__m128.
  • 输出也应该__m128以[-1.0f,0.0f,1.0f]作为其值

我尝试过这个,但它不起作用(虽然我认为它应该):

inputVal = _mm_set_ps(-0.5, 0.5, 0.0, 3.0);
comp1 = _mm_cmpgt_ps(_mm_setzero_ps(), inputVal);
comp2 = _mm_cmpgt_ps(inputVal, _mm_setzero_ps());
comp1 = _mm_castsi128_ps(_mm_castps_si128(comp1));
comp2 = _mm_castsi128_ps(_mm_castps_si128(comp2));
signVal = _mm_sub_ps(comp1, comp2);
Run Code Online (Sandbox Code Playgroud)

2)有没有办法创建"标志"功能(我不确定正确的名称).即,如果A > B结果将是10否则.结果应该是float-point(__m128),就像它的输入一样.

更新:Cory Nelson的回答似乎在这里有效:

__m128 greatherThanFlag = _mm_and_ps(_mm_cmpgt_ps(valA, valB), _mm_set1_ps(1.0f));    
__m128 lessThanFlag = _mm_and_ps(_mm_cmplt_ps(valA, valB), _mm_set1_ps(1.0f));
Run Code Online (Sandbox Code Playgroud)

x86 sse x86-64 simd vectorization

5
推荐指数
2
解决办法
815
查看次数

AVX2由8个__m256i寄存器表示的矩阵的转置

我试图找出如何转置(在AVX2内部函数中)矩形矩阵,该矩形矩阵由8行__m256i寄存器组成,每行包含32x 8位(字符)。

__m256i matrix[8]; //32x8bit integers
Run Code Online (Sandbox Code Playgroud)

转置的矩阵就像32行的8x 8位整数,但我也可以用相同的方式表示它:8行的__m256i,每行包含4行的64位。

我知道_mm256_shuffle_epi8适用于此类问题,但是我不知道如何在矩形矩阵的这种特殊情况下使用它。

c x86 transpose simd avx2

4
推荐指数
1
解决办法
151
查看次数

绩效评估的惯用方法?

我正在评估我的项目的网络+渲染工作负载。

程序连续运行一个主循环:

while (true) {
   doSomething()
   drawSomething()
   doSomething2()
   sendSomething()
}
Run Code Online (Sandbox Code Playgroud)

主循环每秒运行 60 多次。

我想查看性能故障,每个程序需要多少时间。

我担心的是,如果我打印每个程序的每个入口和出口的时间间隔,

这会导致巨大的性能开销。

我很好奇什么是衡量性能的惯用方法。

日志打印是否足够好?

benchmarking microbenchmark

1
推荐指数
1
解决办法
1322
查看次数