我有l任何类型的对象的大型Python列表,还有另一个指向 list 中某些元素的整数索引的大型列表i(甚至NumPy数组)l。
问题是创建另一个列表的最快(最有效)的方法是什么,l2该列表包含 的元素l以及来自 的索引i。
最简单的方法是进行列表理解:
l2 = [l[si] for si in i]
# Use np.nditer(i) instead of i, for NumPy array case
Run Code Online (Sandbox Code Playgroud)
但这是最快的方法吗?
列表理解是一个 Python 循环,因此对于大型列表可能会很慢,也许标准库中有一些内置的 Python 方法可以高效编写C来实现此任务?或者也许NumPy有这样的方法通过 numpy 数组索引 Python 列表?
也许标准 python 库中有一些简单快速的函数可以对 NumPy 的np.take执行相同的操作,如下面的假想代码所示:
import listtools
l2 = listtools.take(l, indexes)
Run Code Online (Sandbox Code Playgroud) 我正在为NumPy寻找最好的64-bit(或至少是32-bit)具有下一个属性的哈希函数:
dtype. 为此,这种散列能够仅处理原始字节块就足够了。xxhash.64-bit整数或更大的输出,但如果是,32-bit那么仍然可以,尽管不是那么可取。如果可能的话,最好选择生成 32、64、128 位大小的散列。xxhash如果它有numpy数组矢量化,我会使用上面链接提到的。但是现在它只是单个对象,它的绑定函数每次调用只接受一个字节块,产生一个整数输出。并且 xxhash 每次调用小(4、8 个字节)输入时只使用几个 CPU 周期,因此可能在大数组上执行纯 Python 循环来为每个数字调用 xxhash 效率非常低。
我需要它用于不同的事情,一个是概率存在过滤器(或集合),即我需要设计这样的结构(集合),N如果请求的元素可能在集合中或不是。为此,我想使用较低的散列位将输入分布到K存储桶中,并且每个存储桶还存储一些(可调整的)较高位的数量,以增加正确答案的概率。另一个应用是布隆过滤器。我需要这个集合在添加和请求时非常快,并且在内存中尽可能紧凑,并处理非常多的元素。
如果没有现有的好的解决方案,那么也许我还可以改进xxhash库并向作者的存储库创建拉取请求。
import numba
@numba.njit
def f(x, c):
for i in range(3):
if c == 0:
x += 1
elif c == 1:
x *= 2
else:
assert False
return x
print(f(3, 0), f(3, 1))
Run Code Online (Sandbox Code Playgroud)
c如果是来自小的最终整数值集的某个常数,例如,如何优化它0 <= c <= 3?
不允许将if有关条件c移出循环,因为这将是一个明显的优化。因为它是一个人为的示例,所以在实际示例中,循环可能会很大,并且仅更改主体内部的 1-2 行即可重复循环两次是负担不起的。
基本上我想让c编译时保持不变。与C++一样,可以将编译时常量作为模板参数,并执行与此相关的所有代码优化。
所以我想告诉 Numba 参数c0、c1等是编译时常量,应该以这样的方式处理:每当使用不同的cNumba 值调用函数时,都应该创建和编译一个单独的函数实例并进行必要的优化,就像C++生成一样当传递新的模板参数集时,模板化函数的每次实例化。
换句话说,这些常量的可能值c应该包含在函数的签名中,据我了解,Numba 会为每个不同的签名生成单独的函数代码,就像 C++ 模板一样。
另一种需要优化的情况是,whenc不是函数的参数,而是循环开始之前某些复杂表达式计算的结果。在这种情况下,结果c …
我想在代码的某个点检查是否x声明了某个标识符,我该怎么做?
我需要对不同类型的标识符进行这种检查 - 变量、枚举常量、函数、类型、宏等。但首先我想至少检查变量和函数。
我需要这样的检查(例如虚数declared(x)),以便下一个代码适用于 int 变量的情况x:
if constexpr(declared(x)) {
int y = x + 1;
} else {
std::cout << "Variable 'x' not declared!" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
对于原因宏的情况,我可以使用#ifdef x,但是如何对变量/函数进行相同的检查?
对于全局非 lambda 函数的情况,我根据重载函数解析计算出了下一个代码,但它需要使用基于辅助宏的全局定义(可以进一步简化吗?):
#include <iostream>
#include <type_traits>
#define declared_func_helper(x, ...) \
struct NotDeclared; \
template <typename ... Args> \
NotDeclared x(Args ...); \
template <typename ... Args> \
inline constexpr bool declared_func_##x(Args && ... args) { \
return !std::is_same_v<decltype(x(args...)), NotDeclared>; \ …Run Code Online (Sandbox Code Playgroud) eular 项目中有第 10 个问题。
问题是求所有不大于N的素数之和。
我对这个问题的解决方案是:
int solve(int n){
bool check[n+1];
for(int i=0;i<=n;i++){
check[i]=true;
}
for(int i=2;i*i<=n;i++){
if(check[i]){
for(int j=i*i;j<=n;j+=i){
check[j]=false;
}
}
}
int sum=0;
for(int i=2;i<=n;i++){
if(check[i]){
sum+=i;
}
}
return sum;
}
Run Code Online (Sandbox Code Playgroud)
但问题仍然没有得到足够的优化,因为我收到了“由于超时而终止”的消息。
我怎样才能更好地优化这段代码。
限制条件是:
1<= T <= 10^4 ( T 是测试用例的数量 )
1<=N<=10^6
你可以在这里自己尝试一下
如果我有编译时间常数,num_bits如何获得可以容纳这么多位的最小整数类型?
我当然可以这样做:
#include <cstdint>
#include <type_traits>
std::size_t constexpr num_bits = 19;
using T =
std::conditional_t<num_bits <= 8, uint8_t,
std::conditional_t<num_bits <= 16, uint16_t,
std::conditional_t<num_bits <= 32, uint32_t,
std::conditional_t<num_bits <= 64, uint64_t,
void>>>>;
Run Code Online (Sandbox Code Playgroud)
但也许标准库中存在一些现成的元函数来实现这个目标?
我创建这个问题只是为了专门从标准库中找出单个元函数。但是,如果除了我提出的上述解决方案之外,您还有其他好的建议如何解决此任务,那么也请发布此类解决方案......
更新。正如评论中所建议的,uint_leastX_t应该使用而不是uintX_t在上面的代码中的任何地方使用,因为uintX_t在某些平台上可能不存在,但uint_leastX_t始终存在。
下一个代码在 CLang/GCC 中编译,并成功内联 lambda:
#include <iostream>
int main() {
int x = 0;
auto f = [&]() __attribute__((always_inline)) {
++x;
};
f();
std::cout << x;
}
Run Code Online (Sandbox Code Playgroud)
但是与__forceinline最新的 MSVC(2019 v16.8.3)中的类似代码无法编译,尽管已宣布在 v16.7 中实现:
#include <iostream>
int main() {
int x = 0;
auto f = [&]() __forceinline {
++x;
};
f();
std::cout << x;
}
Run Code Online (Sandbox Code Playgroud)
抛出编译错误0305.cpp(5): error C3260: 'type': skipping unexpected token(s) before lambda body。
它真的还没有实现还是我用__forceinline错了地方?有没有其他方法可以在 MSVC 中强制内联 lambda?
在所有流行的编译器(例如 CLang/GCC/MSVC)中是否有任何方法不编译代码(并抛出编译错误),以防在某些地方使用给定的 lambda …
文档中说 CLang 中的模块支持是部分的。我在最近发布的 LLVM 12.0 中在 Windows 64 位下使用 CLang。
我成功地设法使用了常规模块(您通过 导入import modulename;)。
但我还没有设法创建和使用头单元模块,那些你通过import "header.hpp";. 你能建议如何用例子做到这一点吗?
为了尝试标题单元,我创建了下一个玩具文件:
你好.hpp:
#include <vector>
Run Code Online (Sandbox Code Playgroud)
使用.cpp:
import "hello.hpp";
int main() {
std::vector<int> v(123);
}
Run Code Online (Sandbox Code Playgroud)
然后我成功(我希望)将头单元编译hello.hpp成 PCM 文件:
clang++ -std=c++20 -Xclang -emit-header-module -I. hello.hpp -o hello.pcm
Run Code Online (Sandbox Code Playgroud)
命令运行没有错误并产生hello.pcm. 如果您在没有-o标志的情况下运行上面的命令,hello.hpp.gch则会创建文件
。
然后我尝试编译use.cpp,但没有成功,不知何故它无法识别我的头单元和/或找不到相应的hello.pcm. 我想我错过了一些特殊的标志,这些标志表明编译器是头单元。使用了下一个命令:
clang++ -std=c++20 -fprebuilt-module-path=. -fmodule-file=hello.hpp=hello.pcm -I. use.cpp
Run Code Online (Sandbox Code Playgroud)
这给了编译错误:
use.cpp:1:8: error: header file "hello.hpp" (aka './hello.hpp') cannot be imported …Run Code Online (Sandbox Code Playgroud) 我有一个大的内存数组作为一些指针uint64_t * arr(加上大小),它代表普通位。我需要非常有效(性能最高/速度最快)将这些位从 0 向右移动一定量到 63。
通过移动整个数组,我的意思是不移动每个元素(如a[i] <<= Shift),而是将其作为单个大位向量移动。换句话说,对于每个中间位置i(第一个和最后一个元素除外),我可以在循环中执行以下操作:
dst[i] = w | (src[i] << Shift);
w = src[i] >> (64 - Shift);
Run Code Online (Sandbox Code Playgroud)
其中w是一些临时变量,保存前一个数组元素的右移值。
上面这个解决方案简单明了。但我需要更高效的东西,因为我有千兆字节的数据。
理想情况下,为此使用一些 SIMD 指令,因此我正在寻找专家的 SIMD 建议。我需要为所有四种类型的流行指令集实现移位代码 - SSE-SSE4.2 / AVX / AVX-2 / AVX-512。
但据我所知,例如 SSE2 只存在_mm_slli_si128()内在/指令,它仅移位 8 的倍数(换句话说,字节移位)。我需要按任意位大小进行移位,而不仅仅是字节移位。
如果没有 SIMD,我也可以通过 using 指令一次移位 128 位shld reg, reg, reg,这允许进行 128 位移位。它在 MSVC 中作为内部__shiftleft128()实现,并生成可以在此处看到的汇编代码。
顺便说一句,我需要所有 MSVC/GCC/CLang 的解决方案。
另外,在单循环迭代中,我可以在顺序操作中移位 4 或 8 个字,这将使用 …
众所周知,C++ 内置类型 uint32_t、int32_t、uint64_t、int64_t 甚至 GCC/CLang 内置类型 __int128 和 unsigned __int128 的 sizeof 都恰好等于位宽除以 8。
但是,如果打印 Boost 的 sizeof boost::multiprecision::uint256_t,uint512_t则 uint256_t 会得到 48 字节而不是 32 字节,uint512_t 会得到 80 字节而不是 64 字节。两种类型的 sizeof 都比预期多 16 个字节。请参阅此处的演示。
但 sizeofboost::multiprecision::uint128_t恰好给出了预期的 16 个字节。
Boost 的所有整数的基类似乎cpp_int_base有几个字段:
data_type m_data;
unsigned m_limbs;
bool m_sign, m_internal, m_alias;
Run Code Online (Sandbox Code Playgroud)
只有 m_data 字段包含整数位,而其他字段则额外提供了 16 个不必要的 sizeof 字节。
我的问题是否可以以某种方式调整 Boost 多精度整数,使其仅包含数据位而不包含其他内容?
换句话说,它保持符号(如果是有符号整数)与Intel CPU将其保留在int64_t中相同,基本上最高位是符号位,其余位以符号补码形式编码。因此 Boost 整数的编码与默认的 intel uint64_t、int64_t 相同。
如果您查看模板的签名,cpp_int_base您会看到:
template <unsigned …Run Code Online (Sandbox Code Playgroud) c++ ×7
python ×3
arrays ×2
c++20 ×2
numpy ×2
performance ×2
algorithm ×1
avx ×1
bigint ×1
boost ×1
c++-modules ×1
c++23 ×1
clang ×1
declaration ×1
function ×1
hash ×1
inline ×1
lambda ×1
list ×1
numba ×1
optimization ×1
primes ×1
reflection ×1
simd ×1
sse ×1
templates ×1
variables ×1
visual-c++ ×1
x86-64 ×1