小编zeb*_*h49的帖子

C(++)struct强制额外填充

我已经看到了无数问题的形式"我不喜欢填充如何关闭它",但还没有找到任何关于强制编译器提供额外填充的内容.

我的具体情况看起来像

struct particle{
  vect2 s;
  vect2 v;
  int rX;
  int rY;
  double mass;
  int boxNum;
};
Run Code Online (Sandbox Code Playgroud)

哪里vect2很简单struct {double x; double y;} vect2.为了使用SSE2,我需要能够加载一对双精度数,对齐到16字节边界.这曾经工作,直到我添加额外的int,将我的结构大小从48字节推到56字节.结果是段错误.

是否有某种编译器指令我可以使用"填充此结构使其成为16字节长的倍数",或"此结构具有16字节的对齐"?我知道我可以手动完成(例如,添加一个额外的字符[12]),但我真的只是告诉编译器(GCC,最好是ICC兼容),如果我改变它,就不必手动完成结构在未来.

c c++ gcc struct memory-alignment

9
推荐指数
3
解决办法
6114
查看次数

为什么从左上角开始测量图形坐标?

我注意到我曾经使用的每个计算机图形系统都使用左手坐标系,其原点位于左上角.Cairo,Java,Microsoft XYZ和大多数图形程序都使用这个系统.我假设他们都追溯到一个共同的祖先,但我找不到任何关于这个的参考.

如果我不得不猜测我会说它来自VGA图形模式,使用与文本相同的坐标,这自然是基于如何自上而下,左右读取英语语言,下面是"第二行" "第一线"......但我正在努力.

周围有人讲述这个故事,还是能指出我正确的历史书的方向?

graphics history canvas coordinates

9
推荐指数
1
解决办法
2431
查看次数

确定提交之间的关系

在线性历史中,两个提交A和B可以具有三种状态之一:

  • A和B是相同的提交
  • 严格在B之前
  • B严格在A之前

Git的非线性历史允许四个附加选项

  • A和B共享父母和孩子
  • A和B共享父母而不是孩子
  • A和B分享孩子而不是父母
  • A和B没什么共享

我不确定如何在不使用嫁接点的情况下实现最后两个,但它可能会发生.

我不确定如何完成的是以一种简单的方式确定这种关系 - 目前我只能想到一个有点奇怪的rev-list解决方案,其中一个人单独测试每个案例:

[[ "$a" = "$b" ]] && echo "same"
git rev-list "$b" | grep -q "$a" && echo "a before b"
git rev-list "$a" | grep -q "$b" && echo "b before a"
cat <(git rev-list "$a") <(git rev-list "$b") | sort | uniq -cd | grep -q 2 && echo "A and B share parents"
cat <(git rev-list --children "$a") <(git rev-list --children …
Run Code Online (Sandbox Code Playgroud)

git bash

8
推荐指数
1
解决办法
860
查看次数

SIMD值得吗?有更好的选择吗?

我有一些运行得相当好的代码,但我想让它运行得更好.我遇到的主要问题是它需要一个嵌套的for循环.外部用于迭代(必须连续发生),内部用于所考虑的每个点粒子.我知道我对外面的东西并不多,但我想知道是否有一种方法可以优化:

    void collide(particle particles[], box boxes[], 
        double boxShiftX, double boxShiftY) {/*{{{*/
            int i;
            double nX; 
            double nY; 
            int boxnum;
            for(i=0;i<PART_COUNT;i++) {
                    boxnum = ((((int)(particles[i].sX+boxShiftX))/BOX_SIZE)%BWIDTH+
                        BWIDTH*((((int)(particles[i].sY+boxShiftY))/BOX_SIZE)%BHEIGHT)); 
                        //copied and pasted the macro which is why it's kinda odd looking

                    particles[i].vX -= boxes[boxnum].mX;
                    particles[i].vY -= boxes[boxnum].mY;
                    if(boxes[boxnum].rotDir == 1) {
                            nX = particles[i].vX*Wxx+particles[i].vY*Wxy;
                            nY = particles[i].vX*Wyx+particles[i].vY*Wyy;
                    } else { //to make it randomly pick a rot. direction
                            nX = particles[i].vX*Wxx-particles[i].vY*Wxy;
                            nY = -particles[i].vX*Wyx+particles[i].vY*Wyy;
                    }   
                    particles[i].vX = nX + boxes[boxnum].mX;
                    particles[i].vY = nY + …
Run Code Online (Sandbox Code Playgroud)

c optimization simd

6
推荐指数
1
解决办法
1669
查看次数

更高效的地板方式可以获得数组索引

我有double x,和double y.我需要将其转换成int boxnum,其被定义为(地板)的索引,其中(x,y)在属于WIDTH x HEIGHT同大小的正方形网格BOX_SIZE.超过的坐标WIDTH被包裹回来; 同上HEIGHT.

我目前正在使用:

( (((int)(x))/BOX_SIZE)%WIDTH+ WIDTH*((((int)(y))/BOX_SIZE)%HEIGHT) )
Run Code Online (Sandbox Code Playgroud)

这句话目前占用了我执行时间的20%,如果我对负坐标完全安全,那就更糟糕了(大约40-50%):

( (( ((int)(x)) /BOX_SIZE)%WIDTH+WIDTH)%WIDTH
    +WIDTH*(( (((int)(y)) /BOX_SIZE)%HEIGHT+HEIGHT)%HEIGHT) )
Run Code Online (Sandbox Code Playgroud)

我实际上正在考虑将应用程序完全转换为定点,只是为了避免这种情况,这样我就可以对我想要的部分进行掩码,而不是进行这种可怕的转换.

有没有更好的方法来进行这种双重> int转换?难道是值得的,以确保0<x<WIDTH*BOX_SIZE0<y<HEIGHT*BOX_SIZE这样我就可以放下两个余数操作?(这样做很难在基准测试中不值得,除非它可能是一个重大改进)

编辑:在评论中进行适当的惩罚后,更多细节:

x并且y是一组(多达10 ^ 6)个粒子的坐标.我正在使用一种算法,它要求我在每个时间步,对一个框内的所有粒子做一些简单的求和.因此,我遍历粒子,计算粒子所在的盒子,然后将其用作添加到该盒子的数组索引.粒子通常移动得足够远,以至于它们过去的位置并不能表明它们未来的位置.这也是无序的,这意味着我不能对此做出任何假设.

WIDTH,HEIGHT以及BOX_SIZE在技术上是免费的,只要WIDTHHEIGHT是的偶数倍BOX_SIZE.在实践中,它们都是指定的编译时间,并且是整数BOX_SIZE=1.我从运行一切WIDTH=HEIGHT=4WIDTH=HEIGHT=512,虽然我平时对2(因为为什么不呢?),方功率WIDTH=37;HEIGHT=193应该没有问题的工作.

每个粒子每个时间步执行一次该计算是不可避免的; 在当前实现中,它执行两次.我尝试缓存该值以避免重新计算,但最终基准测试表现更差,所以我回去计算它两次.

基本测试运行10 particles/box * 100 WIDTH * …

c floating-point performance

6
推荐指数
1
解决办法
255
查看次数

CUDA挂在cudaDeviceSynchronize上

我有一段工作了一段时间的GPU代码。我最近做了一些小的算法更改,但是它们没有涉及CUDA部分。

我正在三台Xeon机器上运行生产,每台机器上装有780 Ti。每次运行大约需要三分钟才能完成,但是在此情况下(有5000种情况),有两种情况下应用程序挂了几个小时(直到被杀死)。两者都在同一台机器上。

第二次,我将GDB附加到正在运行的进程,并得到了一个回溯,看起来像

#0  0x00007fff077ffa01 in clock_gettime ()
#1  0x0000003e1ec03e46 in clock_gettime () from /lib64/librt.so.1
#2  0x00002b5b5e302a1e in ?? () from /usr/lib64/libcuda.so
#3  0x00002b5b5dca2294 in ?? () from /usr/lib64/libcuda.so
#4  0x00002b5b5dbbaa4f in ?? () from /usr/lib64/libcuda.so
#5  0x00002b5b5dba8cda in ?? () from /usr/lib64/libcuda.so
#6  0x00002b5b5db94c4f in cuCtxSynchronize () from /usr/lib64/libcuda.so
#7  0x000000000041cd8d in cudart::cudaApiDeviceSynchronize() ()
#8  0x0000000000441269 in cudaDeviceSynchronize ()
#9  0x0000000000408124 in main (argc=11, argv=0x7fff076fa1d8) at src/fraps3d.cu:200
Run Code Online (Sandbox Code Playgroud)

我手动执行了a frame 8; return;来强制完成它,这导致它最终卡在了下一个cudaDeviceSynchronize()调用上。再次执行此操作会使它停留在下一个同步调用上(每次使用相同的帧0到8)。更为奇怪的是,故障发生在主循环的中间,直到第5000次。

杀死它之后,下一个作业将启动并正常运行,因此这似乎不是执行主机的系统性故障。

有什么想法会导致像这样的随机故障吗?

我正在编译并运行V6.0.1,运行驱动程序版本331.62。

c cuda hang

6
推荐指数
0
解决办法
924
查看次数

从tar.gz中提取文件,而不触及磁盘

当前流程:

  1. 我有一个tar.gz文件.(实际上,我有大约2000个,但这是另一个故事).
  2. 我创建一个临时目录,解压缩tar.gz文件,显示100,000个小文件(每个大约600个字节).
  3. 对于每个文件,我将其捕获到一个处理程序中,将其循环到另一个分析程序中,并保存结果.

我正在使用的机器上的临时空间几乎不能同时处理其中一个进程,更不用说它们默认发送的16(超线程双四核).我正在寻找一种方法来执行此过程而不保存到磁盘.我认为单独使用文件的性能损失tar -xf $file -O <targetname>将是令人望而却步的,但它可能是我所坚持的.

有没有办法做到这一点?

编辑:由于两个人已经犯了这个错误,我将澄清:

  • 每个文件代表一个时间点.
  • 每个文件都单独处理.
  • 一旦处理(在这种情况下是傅立叶分析的变体),每个都给出一行输出.
  • 可以将此输出组合起来以执行跨时间自相关等操作.

EDIT2:实际代码:

for f in posns/*; do
    ~/data_analysis/intermediate_scattering_function < "$f"
done | ~/data_analysis/complex_autocorrelation.awk limit=1000 > inter_autocorr.txt
Run Code Online (Sandbox Code Playgroud)

bash tar

5
推荐指数
2
解决办法
4199
查看次数

在AMD Phenom II上,微小的SSE addpd循环比标量略慢?

是的,我读的SIMD代码运行速度比标量代码慢.不,这不是真的重复.

我一直在使用2D数学的东西,并且在将我的代码库从C移植到C++的过程中.我用C打了一些墙,这意味着我真的需要多态,但这是另一个故事.无论如何,我刚才考虑过这个,但它提供了一个使用2D矢量类的绝佳机会,包括常见数学运算的SSE实现.是的,我知道那里有图书馆,但我想亲自去试一下,了解发生了什么,我不会使用比这更复杂的东西+=.

我的实现是通过<immintrin.h>,一个

union {
    __m128d ss;
    struct {
        double x;
        double y;
    }
}
Run Code Online (Sandbox Code Playgroud)

SSE似乎很慢,所以我查看了它生成的ASM输出.在用指针修复一些愚蠢的东西后,我最终得到了以下几组指令,循环运行了十亿次:(处理器是3.7GHz的AMD Phenom II)

SSE启用:1.1到1.8秒(变化)

add      $0x1, %eax
addpd    %xmm0, %xmm1
cmp      $0x3b9aca00, %eax
jne      4006c8
Run Code Online (Sandbox Code Playgroud)

SSE禁用:1.0秒(相当不变)

add      $0x1, %eax
addsd    %xmm0, %xmm3
cmp      $0x3b9aca00, %eax
addsd    %xmm2, %xmm1
jne      400630
Run Code Online (Sandbox Code Playgroud)

我可以从中得出的唯一结论是,addsd速度快于addpd,并且流水线操作意味着额外指令可以通过更快速地部分重叠的能力来补偿.

所以我的问题是:这是否值得,在实践中它实际上会有所帮助,或者我应该不打扰愚蠢的优化并让编译器在标量模式下处理它?

c c++ assembly gcc sse

4
推荐指数
1
解决办法
1158
查看次数

从内部脚本确定解释器

我有一个剧本; 它需要使用bash的关联数组(相信我的那个).

它需要在普通机器上运行,以及某个具有/ bin/bash 3.2的附加机器.

如果我声明解释器是/opt/userwriteablefolder/bin/bash4,我放在那里的bash 4.2的位置,它工作正常..但它只适用于该机器.

我想在我的脚本开头测试,检查解释shell是什么,如果是bash3.2,则调用bash4 $0 $@.问题是我无法找出任何方法来确定解释shell是什么.我真的不愿意做一个基于$ HOSTNAME的决定,但是如果有必要的话会有效(这也很尴尬,因为它需要通过"我们已经完成这个"标志).

出于几个原因,"只有两个脚本"并不是一个好的解决方案.

linux bash interpreter

4
推荐指数
1
解决办法
3062
查看次数

GCC LTO是否执行跨文件死代码消除?

说我有一个功能

void do_something() {
    //....
    #ifdef FEATURE_X
        feature_x();
    #endif
    //....
}
Run Code Online (Sandbox Code Playgroud)

我可以编译并运行它没有任何问题; 如果我想要我可以通过的功能-D FEATURE_X,它的工作原理.

但是,如果我想do_something放入另一个文件(并且每次我决定更改选项时也不必重新编译该文件)该怎么办?如果它在同一个文件中,我会认为

const int FEATURE_X=0;

void do_something() {
    //....
    if(FEATURE_X) {
        feature_x();
    }
    //....
}
Run Code Online (Sandbox Code Playgroud)

将正确使用死代码消除,取消呼叫.如果我把它放在另一个文件中,没有LTO,

extern const int FEATURE_X;

void do_something() {
    //....
    if(FEATURE_X) {
        feature_x();
    }
    //....
}
Run Code Online (Sandbox Code Playgroud)

它不会删除代码(它无法知道).因此,在启用链接时优化的情况下,编译器是否可以检测FEATURE_X链接时的值,确定是否使用了代码,并在适当的情况下将其删除?

gcc dead-code lto

2
推荐指数
1
解决办法
429
查看次数

分配太多内存的性能损失(?)

作为我正在使用的算法(倾向于使用SMP)的新变体的一部分,我正在考虑将我的particles 分类为boxes,每个box都有一个particle* [].我唯一担心的是,由于每个盒子的粒子数量可能会有所变化(在非常罕见的情况下,平均10个已经高达70),我需要大量分配指针数组.我想的可能是5-10%的利用率.

极端情况下将有大约一百万个,所以我们考虑分配内存的半GB.就它将运行的机器而言,这不是一个问题,但我想知道是否存在与大步跨越相关的性能损失(缓存恨它或其他东西).(例如,访问500中的前60个字节).我知道要确保我的步幅宽度不会最终成为64的缓存破坏倍数...

我很乐意在非常罕见的情况下让它失败,只要这个计划能够为我提供足够的性能提升,以便能够在相同的时间内运行更成功的副本.

如果它是相关的,这个代码将主要在Xeon E5620上运行,虽然这会改变,我宁愿做任何特定于架构的事情.

编辑:这是将连续内存中的N个字节的打包数据与在连续内存的更大区域上均匀跨越的N个字节数据进行比较.

c memory performance

0
推荐指数
1
解决办法
451
查看次数