array有没有办法在页边界上分配 numpy 的数据部分(即数据) ?
出于我关心的原因,如果我在 Intel 设备上使用 PyOpenCL,并且我想使用 创建缓冲区CL_MEM_USE_HOST_PTR,他们建议数据 1) 页面对齐,2) 大小为缓存行的倍数。
C 中有多种分配页对齐内存的方法,例如:aligned malloc() in GCC?
出于某种原因,我的一个函数正在调用movaps带有未对齐参数的 SSE 指令,这会导致崩溃。它发生在函数的第一行,其余的都需要在那里发生崩溃,但为了清楚起见省略了。
Vec3f CrashFoo(
const Vec3f &aVec3,
const float aFloat,
const Vec2f &aVec2)
{
const Vec3f vecNew =
Normalize(Vec3f(aVec3.x, aVec3.x, std::max(aVec3.x, 0.0f)));
// ...
}
Run Code Online (Sandbox Code Playgroud)
这是我从调试主要调用它的方式:
int32_t main(int32_t argc, const char *argv[])
{
Vec3f vec3{ 0.00628005248f, -0.999814332f, 0.0182171166f };
Vec2f vec2{ 0.947231591f, 0.0522233732f };
float floatVal{ 0.010f };
Vec3f vecResult = CrashFoo(vec3, floatVal, vec2);
return (int32_t)vecResult.x;
}
Run Code Online (Sandbox Code Playgroud)
这是从CrashFoo函数开头到崩溃行的反汇编:
00007FF7A7DC34F0 mov rax,rsp
00007FF7A7DC34F3 mov qword ptr [rax+10h],rbx
00007FF7A7DC34F7 push rdi
00007FF7A7DC34F8 sub rsp,80h
00007FF7A7DC34FF movaps xmmword …Run Code Online (Sandbox Code Playgroud) 是否有任何安全的方法可以将整数转换为结构?
举个例子:
struct Colour
{
uint8_t A;
uint8_t R;
uint8_t G;
uint8_t B;
};
Run Code Online (Sandbox Code Playgroud)
我转换为整数或从整数转换:
uint32_t myInteger
Colour* myColour = reinterpret_cast<Colour*>(&myInteger);
uint32_t* myInteger2 = reinterpret_cast<uint32_t*>(myColour);
Run Code Online (Sandbox Code Playgroud)
如果我的结构被填充,那么这将不起作用,有什么方法可以保证它有效吗?
我知道这可能不是标准的,但我更喜欢支持主要编译器(Visual Studio 和 GCC)而不是一些位移解决方法,这里已经回答了:Type cast struct to integer c++。
根据我对维基百科的理解,我可以通过以下按位运算找到具有正确对齐方式的下一个最接近元素的索引。
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) 我知道将Eigen类型与动态内存结合使用时会出现对齐问题。因此,我决定Eigen::DontAlign 根据此页面禁用向量化,但是以下代码仍在执行时一致地引发SIGSEGV。如果有人可以阐明为什么会发生,我会很高兴。从我的角度来看,使用Eigen::DontAlign应该使我摆脱了对齐的复杂性。
#include <Eigen/Dense>
#include <vector>
int main()
{
using vec_t = Eigen::Matrix< double, 4, 1, Eigen::DontAlign >;
std::vector< vec_t > foo;
foo.emplace_back( 0.0, 0.0, 0.0, 1.0 );
vec_t vec{ -4.0, 1.0, 3.0, 1.0 };
foo.push_back( vec );
}
Run Code Online (Sandbox Code Playgroud)
GDB输出:
Program received signal SIGSEGV, Segmentation fault.
0x0000000000408bed in Eigen::internal::evaluator<Eigen::PlainObjectBase<Eigen::Matrix<double, 4, 1, 2, 4, 1> > >::packet<0, double __vector(4)>(long long, long long) const (this=0x22fa90, row=0, col=0)
at C:/Dev/Eigen/Eigen/src/Core/CoreEvaluators.h:197
197 return ploadt<PacketType, LoadMode>(m_data + row + col * …Run Code Online (Sandbox Code Playgroud) 考虑以下 C 代码:
#include <stdint.h>
void func(void) {
uint32_t var = 0;
return;
}
Run Code Online (Sandbox Code Playgroud)
-O0GCC 4.7.2 为上述代码生成的未优化(即:选项)汇编代码是:
func:
pushl %ebp
movl %esp, %ebp
subl $16, %esp
movl $0, -4(%ebp)
nop
leave
ret
Run Code Online (Sandbox Code Playgroud)
根据堆栈对准要求所述的系统V ABI,堆栈必须由16个字节每之前对准call指令(该堆栈边界是默认的16个字节时不与该选项改变-mpreferred-stack-boundary)。因此,在函数调用之前,ESP 模16的结果必须为零。
记住这些堆栈对齐要求,我假设在执行leave指令之前以下堆栈的状态表示是正确的:
Size (bytes) Stack ESP mod 16 Description
-----------------------------------------------------------------------------------
| . . . |
------------------........0 at func call
4 | return address |
------------------.......12 at func entry
4 | saved …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) 我非常简单的代码如下所示
#include <iostream>
#include <stdalign.h>
int main() {
char array_char[2] = {'a', 'b'};
float array_float[2] = {1, 2};
std::cout << "alignof(array_char): " << alignof(array_char) << std::endl;
std::cout << "alignof(array_float): " << alignof(array_float) << std::endl;
std::cout << "address of array_char: " << (void *) array_char << std::endl;
std::cout << "address of array_float: " << array_float << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
这段代码的输出是
alignof(array_char): 1
alignof(array_float): 4
array_char 的地址:0x7fff5e8ec580
array_float 的地址:0x7fff5e8ec570
alignof算子的结果在意料之中,但是两个数组的真实地址并不一致。无论我尝试了多少次,地址总是 16 字节对齐。
我在 Ubuntu 16.04 和 Intel CORE i5 第 7 代 …
如何在C中获取CPU的内存粒度?
假设我想分配一个数组,其中所有元素都正确内存对齐。我可以将每个元素填充到特定大小 N 来实现这一点。我怎么知道N的值?
注意:我正在尝试创建一个内存池,其中每个插槽都是内存对齐的。任何建议将不胜感激。