举例来说,我有一个uint8_t
可以是任何值的值,而我只想将所有位从最低有效位翻转到最高有效的最后 1 位值?我该如何以最有效的方式做到这一点?有没有一种解决方案可以避免使用循环?
以下是一些案例:
左边是原来的位,右边是翻转后的位。
00011101
->00000010
00000000
->00000000
11111111
->00000000
11110111
->00001000
01000000
->00111111
[编辑]
该类型也可以大于uint8_t
,也可以是uint32_t
,uint64_t
和__uint128_t
。我只是使用它uint8_t
,因为它是示例案例中最容易显示的尺寸。
我编写了两个获取数组总和的函数,第一个是用 C++ 编写的,另一个是用内联汇编 (x86-64) 编写的,我比较了这两个函数在我的设备上的性能。
如果在编译期间未启用-O标志,则使用内联汇编的函数几乎比 C++ 版本快 4-5 倍。
cpp time : 543070068 nanoseconds
cpp time : 547990578 nanoseconds
asm time : 185495494 nanoseconds
asm time : 188597476 nanoseconds
Run Code Online (Sandbox Code Playgroud)
如果-O标志设置为-O1,它们会产生相同的性能。
cpp time : 177510914 nanoseconds
cpp time : 178084988 nanoseconds
asm time : 179036546 nanoseconds
asm time : 181641378 nanoseconds
Run Code Online (Sandbox Code Playgroud)
但是,如果我尝试将-O标志设置为-O2或-O3,则使用内联汇编编写的函数会得到不寻常的2-3 位纳秒性能,该性能速度很快(至少对我来说,请耐心等待,因为我对汇编编程没有扎实的经验,所以我不知道它与用 C++ 编写的程序相比有多快或多慢。)
cpp time : 177522894 nanoseconds
cpp time : 183816275 nanoseconds …
Run Code Online (Sandbox Code Playgroud)我目前正在尝试找到一种干净的方法来创建模板化的字节数组结构,该结构可以根据其构造函数是否使用或不使用 constexpr 关键字实例化来进行不同的初始化,并且如果可能的话,我还想将其应用于其他方法和函数,我想知道是否有办法实现这一点?
这是我想要实现的目标的示例:
#include <iostream>
#include <cstring>
template<size_t N>
struct bytearray {
char data[N];
constexpr bytearray(char val) : data() {
if constexpr (... is compile time instantiated ...) {
for (size_t i = 0; i < N; ++i) {
data[i] = val;
}
} else {
std::memset(data, val, N);
}
}
};
int main() {
constexpr bytearray<10> A(7);
bytearray<10> B(7);
}
Run Code Online (Sandbox Code Playgroud)
因此,A
在编译时实例化该类将使用for
循环,memcpy
如果不是的话。
c++ templates template-meta-programming constexpr compile-time-type-checking
当调用 JNI 函数时,Get<PrimitiveType>ArrayElements
它将返回一个 CJNI NativeType
指针数组,该数组可能是原始 JARRAY 的副本,或者是直接指向 JARRAY 原始值的指针。
Release<PrimitiveType>ArrayElements
当模式为0
orJNI_ABORT
且jboolean
输出*isCopy
设置为时,它还有相应的释放缓冲区JNI_TRUE
,但如果模式为 则不释放缓冲区JNI_COMMIT
。
所以我的问题是,如果我们将相应的模式设置为因为该模式不会释放缓冲区,那么我们是否应该free
/完成后delete[]
返回的指针?Get<PrimitiveType>ArrayElements
Release<PrimitiveType>ArrayElements
JNI_COMMIT
JNI_COMMIT 复制回内容但不释放 elems 缓冲区
[编辑]
我的缺点是我没有立即看到它Get<PrimitiveType>ArrayRegion
不返回数组指针,我将原来的第二个问题更新为主要问题。
因此,我目前正在研究按位运算符和位操作,并且遇到了两种不同的方法将四个 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)