我不确定问这个问题的最佳地点在哪里,但我目前正在使用 ARM 内在函数并遵循本指南:https : //developer.arm.com/documentation/102467/0100/Matrix-multiplication-example
但是,那里编写的代码假设数组是按列优先顺序存储的。我一直认为 C 数组是按行优先存储的。他们为什么要这样假设?
编辑:例如,如果不是这样:
void matrix_multiply_c(float32_t *A, float32_t *B, float32_t *C, uint32_t n, uint32_t m, uint32_t k) {
for (int i_idx=0; i_idx < n; i_idx++) {
for (int j_idx=0; j_idx < m; j_idx++) {
for (int k_idx=0; k_idx < k; k_idx++) {
C[n*j_idx + i_idx] += A[n*k_idx + i_idx]*B[k*j_idx + k_idx];
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
他们这样做了:
void matrix_multiply_c(float32_t *A, float32_t *B, float32_t *C, uint32_t n, uint32_t m, uint32_t k) {
for (int i_idx=0; i_idx …Run Code Online (Sandbox Code Playgroud) 考虑汇编代码 -mov edi, offset newarray
根据我所阅读的内容,这会将 的地址newarray放入寄存器edi
我不明白的是这个术语 这个术语offset的英文含义如何
适合这里。
段寄存器用于将可寻址存储器的范围从 64K 字节增加到 1M 字节。但是,我很难理解堆栈段寄存器(SS),因为堆栈已经有两个与之关联的其他寄存器:sp和bp。
假设我将SS设置为5000h ,然后决定通过初始化bp和sp寄存器来初始化堆栈。最初堆栈应该是空的。因此,sp和bp最初应该具有相同的内容。我可以使用任何随机地址初始化sp吗?或者我会有一些限制吗?
例如,用地址7000h初始化sp可以吗
assembly bootloader memory-segmentation x86-16 stack-pointer
如果我这样做:
const char *str = "some assembly instructions";
asm(str);
Run Code Online (Sandbox Code Playgroud)
CLion 会说“'asm' 中的预期字符串文字”
我想使用异步函数调用。我选择了boost::deadline_timer。
对我来说,硬件计时器是一种特定的硬件(令人惊讶),它独立于 CPU 工作,仅用于监视时间。同时,如果我理解正确,它也可以用于设置超时并在达到超时时产生中断。(计时器)
其主要优点是异步执行。设置定时器的线程可以继续工作,回调函数将在设置定时器的同一线程中触发。
让我描述一下我在行动中看到的情况。
应用程序包含一个或多个工作线程。例如,他们处理输入项目并过滤它们。让我们考虑应用程序有 5 个线程,每个线程设置一个计时器(5 秒)。
应用程序正在运行。例如当前线程是thread-3.
计时器 ( thread-0) 已到期并生成(可能是错误的术语)中断。
线程上下文切换 ( thread-3-> thread-0);
回调函数执行;
计时器 ( thread-1) 已到期并产生中断。
...
等等
PS0。我知道这不仅仅是多线程应用程序的一种可能情况。
问题:
我是否正确描述了工作过程?
难道我理解正确的话,即使当前线程是thread-0它也导致上下文切换,因为线程必须停止执行当前的代码,并切换到执行从回调机能的研究码?
如果每个线程设置 100k 或 500k 计时器,它将如何影响性能?
硬件是否有计时器计数的限制?
更新计时器的超时时间有多昂贵?
我正在编写一个小程序,用 printf("\219") 打印一个多边形,看看我正在做的事情是否适合我的内核。但它需要调用很多函数,我不知道x86处理器是否可以接受那么多子例程,而且我在google中找不到结果。所以我的问题是它是否会接受这么多函数调用以及最大值是多少。(我的意思是这样的:-)
function a() {b();}
function b() {c();}
function c() {d();}
...
Run Code Online (Sandbox Code Playgroud)
我已经使用了 5 个这样的级别(你知道我的意思,对吧?)
On Intel machines, integer division requires a sequence of two instructions:
\n因此,我目前正在研究按位运算符和位操作,并且遇到了两种不同的方法将四个 1 字节字组合成一个 4 字节宽字。
下面给出了两种方式
找到这两种方法后,我比较了两者生成的反汇编代码(使用带 -O2 标志的 gcc 11 编译),我没有反汇编及其生成的代码的基本知识,我只知道代码越短,函数速度越快(大多数时候我猜......也许有一些例外),现在对于这两种方法来说,它们在生成的反汇编代码中似乎具有相同的行数/行数,所以我猜他们的表现是一样的?
我也对指令的顺序感到好奇,第一种方法似乎交替其他指令sal>or>sal>or>sal>or,而第二种方法更统一,sal>sal>sal>or>or>mov>or这对性能是否有一些重大影响,例如,如果我们正在处理更大的单词?
两种方法
int method1(unsigned char byte4, unsigned char byte3, unsigned char byte2, unsigned char byte1)
{
int combine = 0;
combine = byte4;
combine <<=8;
combine |= byte3;
combine <<=8;
combine |= byte2;
combine <<=8;
combine |= byte1;
return combine;
}
int method2(unsigned char byte4, unsigned char byte3, unsigned char byte2, unsigned char byte1)
{
int combine = 0, temp;
temp = byte4;
temp …Run Code Online (Sandbox Code Playgroud) 在讨论 32 位 MIPS 架构时,Patterson-Hennessy 解释说静态数据段开始于0x 1000 0000,结束于0x 1000 FFFF,全局指针$gp默认设置为中间地址0x 1000 8000。据说堆是下一个,因此应该从 开始0x 1001 0000。
然而,一些 MARS 实验告诉我,中间有一个额外的段,从0x 1001 0000到0x 1003 FFFF,因此堆仅从 开始0x 1004 0000。事实上,当我使用系统调用在堆上存储数组时,该数组将被存储在0x 1004 0000以后的位置。
.data当我在程序标题下初始化数据时,似乎会使用这个附加段。这让我感到困惑,因为我期望在下面初始化的数据.data被认为是静态的,因此应该存储在由全局指针控制的段中。
问题。MARS 标准表现出的行为吗?如果是,那么位于静态数据和堆之间的这个附加数据段与位于其前面的静态数据段有何不同?
我用 C 语言编写了一个非常简单的函数,它使用strlen()from<string.h>返回变量的长度char*:
int length(char *str) {
return strlen(str);
}
Run Code Online (Sandbox Code Playgroud)
以下是相应的 x86_64 程序集objdump -M intel -d a.out:
00000000000011a8 <length>:
11a8: f3 0f 1e fa endbr64
11ac: 55 push rbp
11ad: 48 89 e5 mov rbp,rsp
11b0: 48 83 ec 10 sub rsp,0x10
11b4: 48 89 7d f8 mov QWORD PTR [rbp-0x8],rdi
11b8: 48 8b 45 f8 mov rax,QWORD PTR [rbp-0x8]
11bc: 48 89 c7 mov rdi,rax
11bf: e8 ac fe ff ff …Run Code Online (Sandbox Code Playgroud) assembly ×8
c ×4
x86 ×4
c++ ×2
asynchronous ×1
bootloader ×1
callstack ×1
division ×1
gcc ×1
lock-free ×1
masm ×1
memory ×1
mips ×1
neon ×1
optimization ×1
terminology ×1
timer ×1
x86-16 ×1
x86-64 ×1