更新2017-05-17.我不再为出现此问题的公司工作,也无法访问Delphi XEx.当我在那里时,问题通过迁移到混合FPC + GCC(Pascal + C)来解决,NEON内在函数用于某些例程,它们有所不同.(强烈建议使用FPC + GCC,因为它可以使用标准工具,特别是Valgrind.)如果有人能够通过可靠的示例演示他们如何实际能够从Delphi XEx生成优化的ARM代码,我很高兴接受答案.
Embarcadero的Delphi编译器使用LLVM后端为Android设备生成本机ARM代码.我有大量的Pascal代码需要编译到Android应用程序中,我想知道如何使Delphi生成更高效的代码.现在,我甚至都没有谈论自动SIMD优化等高级功能,只是关于生成合理的代码.当然必须有一种方法将参数传递给LLVM端,或以某种方式影响结果?通常,任何编译器都会有很多选项来影响代码编译和优化,但是Delphi的ARM目标似乎只是"优化开/关"就是这样.
LLVM应该能够产生合理紧密且合理的代码,但似乎Delphi以一种奇怪的方式使用它的设施.Delphi希望非常频繁地使用堆栈,它通常只利用处理器的寄存器r0-r3作为临时变量.也许是最疯狂的,似乎是将正常的32位整数加载为四个1字节的加载操作.如何让Delphi产生更好的ARM代码,而且没有逐字节麻烦的Android?
起初我认为逐字节加载是用于从big-endian交换字节顺序,但事实并非如此,它实际上只是加载一个带有4个单字节加载的32位数字.*可能是加载完整的32位而不进行未对齐的字大小的内存加载.(是否应该避免这是另一回事,这将暗示整个事情是编译器错误)*
让我们来看看这个简单的函数:
function ReadInteger(APInteger : PInteger) : Integer;
begin
Result := APInteger^;
end;
Run Code Online (Sandbox Code Playgroud)
即使启用了优化,带有更新包1的Delphi XE7以及XE6也会为该功能生成以下ARM汇编代码:
Disassembly of section .text._ZN16Uarmcodetestform11ReadIntegerEPi:
00000000 <_ZN16Uarmcodetestform11ReadIntegerEPi>:
0: b580 push {r7, lr}
2: 466f mov r7, sp
4: b083 sub sp, #12
6: 9002 str r0, [sp, #8]
8: 78c1 ldrb r1, [r0, #3]
a: 7882 ldrb r2, [r0, #2]
c: ea42 2101 orr.w r1, r2, r1, lsl #8
10: 7842 ldrb r2, [r0, #1] …
Run Code Online (Sandbox Code Playgroud) 在我当前的项目中,我使用了多个.so文件.这些位于armeabi和armeabi-v7a文件夹中.不幸的是,其中一个.so文件是6MB,我需要减小文件大小.我想使用armeabi文件并删除armeabi-v7a文件夹,而不是有一个胖的APK文件.
根据NDK文档,armeabi-v7a代码是扩展的armeabi代码,可以包含额外的CPU指令.这一切都超出了我的专业知识,但我怀疑为什么人们想要同时拥有armeabi-v7a和armeabi代码.两者都有充分的理由,对吗?
在我的测试设备上,这一切看起来都很好.这些都有ARM v7 CPU.假设现在一切正常可以安全吗?
我有一个具有时间要求严格的ISR的嵌入式应用程序需要迭代256个大小的数组(最好是1024,但256是最小的),并检查一个值是否与数组内容匹配.如果bool
是这样,A 将设置为true.
微控制器是NXP LPC4357,ARM Cortex M4内核,编译器是GCC.我已经结合优化级别2(3更慢)并将功能放在RAM而不是闪存中.我还使用指针算法和for
循环,它进行向下计数而不是向上(检查是否i!=0
比检查是否更快i<256
).总而言之,我的最终持续时间为12.5μs,必须大幅度降低才能实现.这是我现在使用的(伪)代码:
uint32_t i;
uint32_t *array_ptr = &theArray[0];
uint32_t compareVal = 0x1234ABCD;
bool validFlag = false;
for (i=256; i!=0; i--)
{
if (compareVal == *array_ptr++)
{
validFlag = true;
break;
}
}
Run Code Online (Sandbox Code Playgroud)
什么是绝对最快的方法呢?允许使用内联汇编.其他'不太优雅'的技巧也是允许的.
我正在尝试为我的Ubuntu机器上的Raspberry Pi进行交叉编译.
在我最初的尝试中,我使用的是arm-linux-gnueabi编译器,它可以在Ubuntu repo中找到.我得到了这个工作.我能够构建所有依赖项并在我的cmake项目中使用交叉编译器.
但是,我相信我应该使用hf版本,所以我切换到arm-linux-gnueabihf.然后我意识到这不适用于Raspberry Pi,因为它是armv6.
经过一些谷歌搜索后,我找到了GitHub预先构建的工具链.
我下载了工具链,但我真的不明白如何"安装"它.我将文件解压缩到我的主目录.目录结构如下所示:
/gcc-linearo-arm-linux-gnueabihf-raspbian
/arm-linux-gnueabihf
/bin
(contains g++, gcc, etc)
/lib
(contains libstdc++ library)
/bin
(contains arm-linux-gnueabihf-g++, arm-linux-gnueabihf-...)
/lib
(gcc lib stuff)
Run Code Online (Sandbox Code Playgroud)
如果我将目录更改为INNER bin文件夹,我可以从终端编译测试程序,没有任何问题.
~/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/
arm-linux-gnueabihf/bin$ g++ test.cpp -o test
Run Code Online (Sandbox Code Playgroud)
然后我尝试在OUTER bin文件夹中编译测试程序,该文件夹包含工具的前缀版本.
~/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin$
arm-linux-gnueabihf-g++ test.cpp -o test
Run Code Online (Sandbox Code Playgroud)
但是,当我尝试使用编译器时(从内部bin目录之外),它无法找到工具链附带的libstdc ++共享库:
arm-linux-gnueabihf-gcc: error while loading shared libraries:
libstdc++.so.6: cannot open shared object file: No such file or directory.
Run Code Online (Sandbox Code Playgroud)
此外,我希望能够使用编译器而无需导航到bin目录.所以我尝试添加OUTER bin目录(因为我想要前缀版本)和两个lib目录到我的PATH:
export PATH=$PATH:~/tools/.../bin
export PATH=$PATH:~/tools/.../lib
export PATH=$PATH:~/tools/.../.../lib
Run Code Online (Sandbox Code Playgroud)
但是,这会导致相同的错误.我应该如何"安装"工具链,以便我可以随处使用工具链,就像我使用Ubuntu repo中的交叉编译器一样?
当我用我的交叉工具链编译C代码时,链接器打印警告页面,说我的可执行文件使用硬浮动,但我的libc使用软浮动.有什么不同?
我想在 MacBook M1 上运行 docker 容器Ganache
,但出现以下错误:
The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested
Run Code Online (Sandbox Code Playgroud)
在此行之后,不会再发生任何其他事情,并且整个过程被卡住,尽管根据活动监视器,qemu-system-aarch64 正在 100% CPU 上运行,直到我按CTRL+ C。
我的 docker 文件来自此存储库。遇到相同的问题后,我尝试找出根本原因,并提出了会遇到相同错误的最小设置。
这是以下的输出docker-compose up --build
:
Building ganache
Sending build context to Docker daemon 196.6kB
Step 1/17 : FROM trufflesuite/ganache-cli:v6.9.1
---> 40b011a5f8e5
Step 2/17 : LABEL Unlock <ops@unlock-protocol.com>
---> Using cache
---> aad8a72dac4e
Step 3/17 : RUN apk add --no-cache …
Run Code Online (Sandbox Code Playgroud) 编译器生成的最终图像包含bin文件和扩展加载器格式ELf文件,两者之间有什么区别,尤其是ELF文件的实用程序.
覆盆子裨类型3具有64位CPU,但它的体系结构是不arm64
而是armhf
.arm64
和之间有什么区别armhf
?
这是一个特别在ARM上发生的问题,而不是在x86或x64上.我有这个用户报告的问题,并且能够通过Windows IoT在Raspberry Pi 2上使用UWP重现它.我在使用不匹配的调用约定之前已经看到过这种问题,但是我在P/Invoke声明中指定了Cdecl,我尝试在原生端显式添加__cdecl并获得相同的结果.这是一些信息:
P/Invoke声明(参考):
[DllImport(Constants.DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern FLSliceResult FLEncoder_Finish(FLEncoder* encoder, FLError* outError);
Run Code Online (Sandbox Code Playgroud)
C#结构(参考):
internal unsafe partial struct FLSliceResult
{
public void* buf;
private UIntPtr _size;
public ulong size
{
get {
return _size.ToUInt64();
}
set {
_size = (UIntPtr)value;
}
}
}
internal enum FLError
{
NoError = 0,
MemoryError,
OutOfRange,
InvalidData,
EncodeError,
JSONError,
UnknownValue,
InternalError,
NotFound,
SharedKeysStateError,
}
internal unsafe struct FLEncoder
{
}
Run Code Online (Sandbox Code Playgroud)
C头中的函数(参考)
FLSliceResult FLEncoder_Finish(FLEncoder, FLError*); …
Run Code Online (Sandbox Code Playgroud)