相关疑难解决方法(0)

用翻译复制内存的快速方法 - ARGB到BGR

概观

我有一个图像缓冲区,我需要转换为另一种格式.原始图像缓冲区是四个通道,每通道8位,Alpha,红色,绿色和蓝色.目标缓冲区是三个通道,每通道8位,蓝色,绿色和红色.

所以蛮力方法是:

// Assume a 32 x 32 pixel image
#define IMAGESIZE (32*32)

typedef struct{ UInt8 Alpha; UInt8 Red; UInt8 Green; UInt8 Blue; } ARGB;
typedef struct{ UInt8 Blue; UInt8 Green; UInt8 Red; } BGR;

ARGB orig[IMAGESIZE];
BGR  dest[IMAGESIZE];

for(x = 0; x < IMAGESIZE; x++)
{
     dest[x].Red = orig[x].Red;
     dest[x].Green = orig[x].Green;
     dest[x].Blue = orig[x].Blue;
}
Run Code Online (Sandbox Code Playgroud)

但是,我需要比循环和三字节副本提供的速度更快的速度.鉴于我在32位机器上运行,我希望可以使用一些技巧来减少内存读写次数.

附加信息

每个图像都是至少4个像素的倍数.因此我们可以处理16个ARGB字节并将它们移动到每个循环12个RGB字节.也许这个事实可以用来加快速度,尤其是它可以很好地进入32位边界.

我可以访问OpenCL - 虽然这需要将整个缓冲区移动到GPU内存中,然后将结果移回去,OpenCL可以同时处理图像的许多部分,以及大内存块移动的事实非常有效可能使这个值得探索.

虽然我已经给出了上面的小缓冲区的例子,但我真的正在移动高清视频(1920x1080),有时更大,大多数是更小的缓冲区,所以虽然32x32情况可能是微不足道的,但是逐字节复制8.3MB的图像数据是真的,非常糟糕.

在Intel处理器(Core 2及更高版本)上运行,因此我知道存在流式和数据处理命令,但不知道 - 可能指向寻找专门数据处理指令的指针也不错.

这是进入一个OS X应用程序,我正在使用XCode 4.如果程序集是无痛的并且显而易见的方法,我可以沿着这条路走下去,但是在这个设置上没有这样做之前让我警惕沉没太多时间了.

伪代码很好 - 我不是在寻找一个完整的解决方案,只是算法和任何可能不会立即清楚的技巧的解释.

c algorithm

65
推荐指数
7
解决办法
8159
查看次数

asm,asm volatile和clobbering memory之间的区别

在实现无锁数据结构和时序代码时,通常需要抑制编译器的优化.通常人们在clobber列表中使用asm volatilewith memory,但你有时会看到asm volatile或只是一个简单的asm破坏性记忆.

这些不同的陈述对代码生成有什么影响(特别是在GCC中,因为它不太可能是可移植的)?

仅供参考,这些是有趣的变化:

asm ("");   // presumably this has no effect on code generation
asm volatile ("");
asm ("" ::: "memory");
asm volatile ("" ::: "memory");
Run Code Online (Sandbox Code Playgroud)

c gcc inline-assembly

62
推荐指数
2
解决办法
4万
查看次数

如何在iPhone上进行内联汇编?

怎么做?我需要采取哪些步骤以及需要考虑哪些陷阱和陷阱?

iphone assembly inline-assembly

29
推荐指数
2
解决办法
1万
查看次数

快速检查字符数组是否为零的方法

我在内存中有一个字节数组.查看数组中所有字节是否为零的最快方法是什么?

c memory optimization performance 32-bit

19
推荐指数
2
解决办法
2万
查看次数

如何在内联汇编中通过sysenter调用系统调用?

我们如何在x86 Linux中直接使用sysenter/syscall实现系统调用?有人可以提供帮助吗?如果您还可以显示amd64平台的代码,那就更好了.

我知道在x86中,我们可以使用

__asm__(
"               movl $1, %eax  \n"
"               movl $0, %ebx \n"
"               call *%gs:0x10 \n"
);
Run Code Online (Sandbox Code Playgroud)

间接路由到sysenter.

但是我们如何使用sysenter/syscall直接编码来发出系统调用呢?

我找到了一些材料http://damocles.blogbus.com/tag/sysenter/.但仍然难以弄明白.

linux x86 gcc x86-64 system-calls

19
推荐指数
2
解决办法
1万
查看次数

在C++内联asm中使用基指针寄存器

我希望能够%rbp在内联asm中使用基指针寄存器().这样的玩具示例是这样的:

void Foo(int &x)
{
    asm volatile ("pushq %%rbp;"         // 'prologue'
                  "movq %%rsp, %%rbp;"   // 'prologue'
                  "subq $12, %%rsp;"     // make room

                  "movl $5, -12(%%rbp);" // some asm instruction

                  "movq %%rbp, %%rsp;"  // 'epilogue'
                  "popq %%rbp;"         // 'epilogue'
                  : : : );
    x = 5;
}

int main() 
{
    int x;
    Foo(x);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我希望,因为我使用通常的序幕/结尾函数调用方法来推送和弹出旧的%rbp,这样就可以了.但是,当我尝试在内x联asm之后访问时,它会出现故障.

GCC生成的汇编代码(略微剥离)是:

_Foo:
    pushq   %rbp
    movq    %rsp, %rbp
    movq    %rdi, -8(%rbp)

    # INLINEASM
    pushq %rbp;          // prologue
    movq %rsp, …
Run Code Online (Sandbox Code Playgroud)

c++ x86 assembly red-zone

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

在gcc内联x86_64汇编中约束r10寄存器

我正在编写一个非常轻量级的libc替换库,以便我可以更好地理解内核 - 应用程序界面.第一项任务显然是使一些系统调用包装器到位.我已经成功地获得了1到3个参数包装器,但我正在努力使用4参数varient.这是我的出发点:

long _syscall4(long type, long a1, long a2, long a3, long a4)
{
    long ret;
    asm
    (
        "syscall"
        : "=a"(ret)
        : "a"(type), "D"(a1), "S"(a2), "d"(a3), "r10"(a4)
        : "c", "r11"
    );
    return ret;
}
Run Code Online (Sandbox Code Playgroud)

编译器给我以下错误:

error: matching constraint references invalid operand number
Run Code Online (Sandbox Code Playgroud)

我的_syscall3函数工作正常但不使用r10或有一个clobber列表.

有什么想法吗?

c gcc x86-64 system-calls inline-assembly

9
推荐指数
2
解决办法
1618
查看次数

Google 基准框架不优化

void DoNotOptimize我对Google Benchmark Framework 的功能实现有点困惑(定义来自这里):

template <class Tp>
inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp const& value) {
  asm volatile("" : : "r,m"(value) : "memory");
}

template <class Tp>
inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp& value) {
#if defined(__clang__)
  asm volatile("" : "+r,m"(value) : : "memory");
#else
  asm volatile("" : "+m,r"(value) : : "memory");
#endif
}
Run Code Online (Sandbox Code Playgroud)

因此,它具体化了变量,如果变量非常量,也会告诉编译器忘记有关其先前值的任何信息。("+r"是 RMW 操作数)。

并且总是使用"memory"clobber,这是编译器对重新排序加载/存储的障碍,即确保所有全局可访问的对象的内存与 C++ 抽象机同步,并假设它们也可能已被修改。


我距离成为低级代码专家还很远,但据我了解其实现,该函数充当读/写屏障。因此,基本上,它确保传入的值位于寄存器或内存中。

虽然如果我想保留函数的结果(应该进行基准测试),这似乎是完全合理的,但我对编译器留下的自由度感到有点惊讶。

我对给定代码的理解是,编译器可能会在DoNotOptimize调用时插入物化点,这意味着重复执行时(例如,在循环中)会产生大量开销。当不应优化的值只是单个标量值时,如果编译器确保该值驻留在寄存器中似乎就足够了。

区分指针和非指针不是一个好主意吗?例如:

template< class T >
inline __attribute__((always_inline)) 
void do_not_optimize( …
Run Code Online (Sandbox Code Playgroud)

c++ assembly inline-assembly microbenchmark google-benchmark

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

为什么棕褐色在环境中比孤立时慢?

运行附加的示例程序时,该函数tan在上下文中的速度似乎是孤立时的两倍。这是我机器上的输出:

justtan(): ~16.062430 ns/iter
notan():   ~30.852820 ns/iter
withtan(): ~60.703100 ns/iter
empty():   ~0.355270 ns/iter
Run Code Online (Sandbox Code Playgroud)

鉴于它是和的组合,我预计withtan()约为 45ns 或更低。justtannotan

我正在使用 Intel i7-4980HQ CPU 运行 macOS 11.5.2。我的cc --versionApple clang version 13.0.0 (clang-1300.0.29.3)。我已经检查过,以确保除了对 的调用之外,withtan和 的notan反汇编是相同的tan,并且 clang 使用 VEX 指令对循环进行自动矢量化。我还通过调试器检查了运行时调用的版本tan是否也利用 VEX 指令来避免 SSE-AVX2 转换损失。

我在Linux VM中编译并运行了该程序,并得到了类似的结果(在调试器中,tan也使用AVX/VEX)。此外,我通过cachegrind运行它,发现任何函数基本上都没有L1缓存未命中(0.00%),但是当通过cachegrind运行时,所有时间都正确地加起来。

这就是我运行可执行文件的方式:

cc -Wall -O3 -mavx2 -o main main.c && ./main

这是main.c

justtan(): ~16.062430 ns/iter
notan():   ~30.852820 ns/iter
withtan(): ~60.703100 ns/iter …
Run Code Online (Sandbox Code Playgroud)

c performance x86 clang avx

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

使用GNU C内联汇编在VGA内存中绘制字符

我正在学习用DOS和内联汇编在DOS下做一些低级VGA编程.现在我正在尝试创建一个在屏幕上打印出一个角色的功能.

这是我的代码:

//This is the characters BITMAPS
uint8_t characters[464] = {
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x20,0x20,0x00,0x20,0x00,0x50,
  0x50,0x00,0x00,0x00,0x00,0x00,0x50,0xf8,0x50,0x50,0xf8,0x50,0x00,0x20,0xf8,0xa0,
  0xf8,0x28,0xf8,0x00,0xc8,0xd0,0x20,0x20,0x58,0x98,0x00,0x40,0xa0,0x40,0xa8,0x90,
  0x68,0x00,0x20,0x40,0x00,0x00,0x00,0x00,0x00,0x20,0x40,0x40,0x40,0x40,0x20,0x00,
  0x20,0x10,0x10,0x10,0x10,0x20,0x00,0x50,0x20,0xf8,0x20,0x50,0x00,0x00,0x20,0x20,
  0xf8,0x20,0x20,0x00,0x00,0x00,0x00,0x00,0x60,0x20,0x40,0x00,0x00,0x00,0xf8,0x00,
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x08,0x10,0x20,0x40,0x80,
  0x00,0x70,0x88,0x98,0xa8,0xc8,0x70,0x00,0x20,0x60,0x20,0x20,0x20,0x70,0x00,0x70,
  0x88,0x08,0x70,0x80,0xf8,0x00,0xf8,0x10,0x30,0x08,0x88,0x70,0x00,0x20,0x40,0x90,
  0x90,0xf8,0x10,0x00,0xf8,0x80,0xf0,0x08,0x88,0x70,0x00,0x70,0x80,0xf0,0x88,0x88,
  0x70,0x00,0xf8,0x08,0x10,0x20,0x20,0x20,0x00,0x70,0x88,0x70,0x88,0x88,0x70,0x00,
  0x70,0x88,0x88,0x78,0x08,0x70,0x00,0x30,0x30,0x00,0x00,0x30,0x30,0x00,0x30,0x30,
  0x00,0x30,0x10,0x20,0x00,0x00,0x10,0x20,0x40,0x20,0x10,0x00,0x00,0xf8,0x00,0xf8,
  0x00,0x00,0x00,0x00,0x20,0x10,0x08,0x10,0x20,0x00,0x70,0x88,0x10,0x20,0x00,0x20,
  0x00,0x70,0x90,0xa8,0xb8,0x80,0x70,0x00,0x70,0x88,0x88,0xf8,0x88,0x88,0x00,0xf0,
  0x88,0xf0,0x88,0x88,0xf0,0x00,0x70,0x88,0x80,0x80,0x88,0x70,0x00,0xe0,0x90,0x88,
  0x88,0x90,0xe0,0x00,0xf8,0x80,0xf0,0x80,0x80,0xf8,0x00,0xf8,0x80,0xf0,0x80,0x80,
  0x80,0x00,0x70,0x88,0x80,0x98,0x88,0x70,0x00,0x88,0x88,0xf8,0x88,0x88,0x88,0x00,
  0x70,0x20,0x20,0x20,0x20,0x70,0x00,0x10,0x10,0x10,0x10,0x90,0x60,0x00,0x90,0xa0,
  0xc0,0xa0,0x90,0x88,0x00,0x80,0x80,0x80,0x80,0x80,0xf8,0x00,0x88,0xd8,0xa8,0x88,
  0x88,0x88,0x00,0x88,0xc8,0xa8,0x98,0x88,0x88,0x00,0x70,0x88,0x88,0x88,0x88,0x70,
  0x00,0xf0,0x88,0x88,0xf0,0x80,0x80,0x00,0x70,0x88,0x88,0xa8,0x98,0x70,0x00,0xf0,
  0x88,0x88,0xf0,0x90,0x88,0x00,0x70,0x80,0x70,0x08,0x88,0x70,0x00,0xf8,0x20,0x20,
  0x20,0x20,0x20,0x00,0x88,0x88,0x88,0x88,0x88,0x70,0x00,0x88,0x88,0x88,0x88,0x50,
  0x20,0x00,0x88,0x88,0x88,0xa8,0xa8,0x50,0x00,0x88,0x50,0x20,0x20,0x50,0x88,0x00,
  0x88,0x50,0x20,0x20,0x20,0x20,0x00,0xf8,0x10,0x20,0x40,0x80,0xf8,0x00,0x60,0x40,
  0x40,0x40,0x40,0x60,0x00,0x00,0x80,0x40,0x20,0x10,0x08,0x00,0x30,0x10,0x10,0x10,
  0x10,0x30,0x00,0x20,0x50,0x88,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,
  0x00,0xf8,0xf8,0xf8,0xf8,0xf8,0xf8};
/**************************************************************************
 *  put_char                                                              *
 *     Print char                                                         *
 **************************************************************************/
void put_char(int x ,int y,int ascii_char ,byte color){

    __asm__(
        "push %si\n\t"
        "push %di\n\t"
        "push %cx\n\t"
        "mov color,%dl\n\t"   //test color
        "mov ascii_char,%al\n\t"  //test char
        "sub $32,%al\n\t"
        "mov $7,%ah\n\t"
        "mul %ah\n\t"
        "lea $characters,%si\n\t" …
Run Code Online (Sandbox Code Playgroud)

c x86 gcc dos djgpp

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