array有没有办法在页边界上分配 numpy 的数据部分(即数据) ?
出于我关心的原因,如果我在 Intel 设备上使用 PyOpenCL,并且我想使用 创建缓冲区CL_MEM_USE_HOST_PTR,他们建议数据 1) 页面对齐,2) 大小为缓存行的倍数。
C 中有多种分配页对齐内存的方法,例如:aligned malloc() in GCC?
根据我对维基百科的理解,我可以通过以下按位运算找到具有正确对齐方式的下一个最接近元素的索引。
Assuming the address of the 1st element has the correct alignment.
Assuming the index_alignment is a power of 2.
new_index = (current_index + index_alignment - 1) & ~(index_alignment - 1).
new_address = address_of_1st_element + new_index
index_alignment is 16 bytes/sizeof(type of element) for SSE.
Run Code Online (Sandbox Code Playgroud)
是否可以直接在地址上使用它来从任何给定地址找到下一个最接近的对齐地址?(这样比较快吗?)
为了快速做到这一点,我正在考虑以下事项。
new_address = (current_address + alignment - 1) & ~(alignment -1)
alignment here is 16 for SSE.
Run Code Online (Sandbox Code Playgroud)
当我实现这个时,我发现以下代码无法编译...
根据 Salva 和 Rotem 的建议修复了代码
#include <iostream>
#include <stdint.h>
#define ALIGNMENT 16
using namespace std; …Run Code Online (Sandbox Code Playgroud) struct t1中给出了如何打包struct python。
我看到这里给出了许多示例https://docs.python.org/2/library/struct.html来打包如下值:
pack('hhl', 1, 2, 3)。
但是如何打包示例struct t1中的c类型struct python。
struct s {
int16_t x;
int8_t y;
uint8_t z;
};
struct t1 {
int16_t x;
struct s y;
};
Run Code Online (Sandbox Code Playgroud) 我有以下内容:
#include <stdio.h>
typedef union u_data
{
struct
{
int a;
int b;
int c;
};
int elem[3];
} my_data;
int main(void)
{
my_data data;
data.a = 3;
data.b = 5;
data.c = -3;
printf("%d, %d, %d\n", data.elem[0], data.elem[1], data.elem[2]);
}
Run Code Online (Sandbox Code Playgroud)
它按照我的预期输出:3, 5, -3
但是我知道结构中可以有填充,所以这是否意味着结构中的元素可能并不总是与数组对齐?
说我有一个这样的工会
union blah {
foo f;
bar b;
};
Run Code Online (Sandbox Code Playgroud)
其中 和foo都是bar可简单复制的。这样做安全吗:
blah b;
foo f;
memcpy(&b, &f, sizeof(f));
Run Code Online (Sandbox Code Playgroud)
然后b.f作为活跃的工会成员使用?或者,我是否必须 memcpy 到特定的工会成员,如下所示:
memcpy(&b.f, &f, sizeof(f));
Run Code Online (Sandbox Code Playgroud)
我在实践中担心这一点的原因是因为我将不得不编写一个大致如下的函数:
template<int c>
void init_union(blah& b, typename type_family<c>::type const& t) {
switch (c) {
case 0:
memcpy(&b.p0, &t, sizeof(t));
break;
case 1:
memcpy(&b.p1, &t, sizeof(t));
break;
// etc.
}
}
Run Code Online (Sandbox Code Playgroud)
但我宁愿能够跳过整个 switch 语句并只写这个:
template<int c>
void init_union(blah& b, typename type_family<c>::type const& t) {
memcpy(&b, &t, sizeof(t));
}
Run Code Online (Sandbox Code Playgroud) 根据该标准,new表达式的语法允许alignas提供说明符以及其他属性说明符。我见过其他代码使用这个,但 GCC 会忽略属性说明符,即使它在最大对齐范围内,并且 Clang 会抛出错误。
alignas说明符在表达式中实际上有效吗new?我并不是想解决特定问题,我只是想了解标准。
int* example = new alignas(16) int[2];
// alignof(std::max_align_t) = 16
// sizeof(int) = 4, sizeof(example) = 8
Run Code Online (Sandbox Code Playgroud)
海湾合作委员会:
prog.cc: In function 'int main()':
prog.cc:7:41: warning: attribute ignored [-Wattributes]
7 | int* example = new alignas(16) int[2];
| ^
prog.cc:7:41: note: an attribute that appertains to a type-specifier is ignored
Run Code Online (Sandbox Code Playgroud)
铛:
prog.cc:7:24: error: an attribute list cannot appear here:
int* example = new …Run Code Online (Sandbox Code Playgroud) 最近我观察到,在 Clang 9.0 上,alignof和__alignof返回unsigned long long的不同值,并且在https://reviews.llvm.org/D54814上也讨论了同样的问题:
从 Clang 8.0 和 GCC 8.0 开始,在相同情况下返回不同的值
alignof。__alignof具体而言alignof,and_Alignof返回类型的最小对齐方式,其中 as__alignof返回首选对齐方式。
我了解类型对齐,但从未遇到过“最小对齐”和“首选对齐”。
有人可以帮我理解这些到底是什么以及有什么区别吗?谢谢。
_mm_load_ps() SSE 内在函数被定义为对齐的,如果地址未对齐则抛出异常。然而,视觉工作室似乎生成了未对齐的读取。
由于并非所有编译器都是相同的,这隐藏了错误。如果能够打开实际的对齐操作,那就太好了,尽管以前的性能影响似乎不再存在了。
换句话说,编写代码:
__m128 p1 = _mm_load_ps(data);
Run Code Online (Sandbox Code Playgroud)
目前生产:
movups xmm0,xmmword ptr [eax]
Run Code Online (Sandbox Code Playgroud)
预期结果:
movaps xmm0,xmmword ptr [eax]
Run Code Online (Sandbox Code Playgroud)
(我是被微软要求来这里问的)
我正在学习结构填充,并了解到结构填充背后的原因是,如果结构的成员未对齐,处理器将无法仅在一个周期内读取/写入它们。一般来说,由N字节组成的数据类型的位置应该是 的倍数的地址N。
假设这个结构体例如:
struct X
{
char c;
// 3 bytes padding here so that i is aligned.
int i;
};
Run Code Online (Sandbox Code Playgroud)
这里这个结构体的大小应该是8个字节,c默认是对齐的,因为它只占用1个字节,但i事实并非如此。对于i,我们需要在其前面添加 3 个字节的填充,使其“对齐”并且只能在一个周期内访问。告诉我我是否遗漏了什么。
1 - 对齐是如何工作的?成员们的立场是什么?
2 - 对于 CPU 访问N位于 的倍数地址的字节数据类型,什么更好N?例如,在上面的结构体中,如果i位于地址XXX3(以 3 结尾,换句话说,不是 4 的倍数),为什么不读取从地址开始的单词XXX3?为什么一定是4的倍数?大多数 CPU 访问的地址是否仅为字大小的倍数?我相信 CPU 可以从内存中的任意字节开始读取一个字。我错了吗?
3 - 为什么编译器不重新排序成员以便占用尽可能多的空间?顺序重要吗?我不确定是否有人使用实际的偏移量来访问成员。这意味着如果有一个 struct X x,通常会像这样访问成员:x.inot *(&x + 4)。在后一种情况下,顺序实际上很重要,但在第一种情况下(我相信每个人都使用),顺序不重要。我必须注意,在这个例子中,这并不重要,因为如果也i出现在前面c,那么末尾会有 3 个字节的填充。我一般都问为什么? …
在我的矩阵类中,我按如下方式分配对齐内存:
/*** main.cpp ***/
#include "matrix.hpp"
int main()
{
{
Matrix(15, 17);
}
return 0;
}
/** matrix.hpp **/
class Matrix
{
private:
std::size_t width_, height_;
double* data_;
public:
Matrix(std::size_t width, std::size_t height);
~Matrix();
};
/** matrix.cpp **/
Matrix::Matrix(std::size_t width, std::size_t height)
: width_(width)
, height_(height)
{
data_ = new(std::align_val_t{64}) double[width_ * height_];
}
Run Code Online (Sandbox Code Playgroud)
我该如何正确删除它?
我都尝试过
Matrix::~Matrix()
{
delete[] data_;
}
Run Code Online (Sandbox Code Playgroud)
和
Matrix::~Matrix()
{
delete[](std::align_val_t{64}, data_);
}
Run Code Online (Sandbox Code Playgroud)
但我收到错误:
SIGTRAP (Trace/breakpoint trap)
ntdll!RtlIsNonEmptyDirectoryReparsePointAllowed 0x00007ffe5dc390e3
ntdll!RtlpNtMakeTemporaryKey 0x00007ffe5dc41512
ntdll!RtlpNtMakeTemporaryKey 0x00007ffe5dc4181a
ntdll!RtlpNtMakeTemporaryKey 0x00007ffe5dc4a7d9
ntdll!RtlGetCurrentServiceSessionId …Run Code Online (Sandbox Code Playgroud) c++ memory-management memory-alignment new-operator delete-operator
memory-alignment ×10
c++ ×6
struct ×3
c ×2
padding ×2
unions ×2
c++11 ×1
clang ×1
intrinsics ×1
memcpy ×1
new-operator ×1
numpy ×1
opencl ×1
pyopencl ×1
python ×1
sse ×1
visual-c++ ×1