在某些C++代码中,我使用整数来存储大量不断变化的数据.为了分析我的程序,我想记录某些变量的某些更改,例如指定某个值的频率,以及该赋值冗余的频率(新值与旧值相同).
如果类型是类Foo,我只是派生一个新的LoggingFoo并将我的日志记录数据添加到我感兴趣的成员函数中,然后调用父成员函数.我必须更新我的代码才能使用新类型,但只要我最初与typedef一致,那就是单行更改.
我的问题是我想要添加日志记录的变量是一个int.您无法从C++中的内置类型派生(可以吗?)
我的问题是,是否有一种聪明的方法来从基本类型(int,float,double等)派生.
解决方案可能是定义一个有效地为int 的新类.它定义了int可以执行的每个操作,并将该操作应用于私有int数据成员.这个策略可行,但也许其他人已经创建了这样的类,我可以使用"fakeint.h"头文件定义.在我自己实现之前,是否有某种"代理本机类包装"类型定义已经可用?
我确实认识到我的代理int当然不能与int互换使用,特别是因为现有的函数定义都期望一个int ..但对于我的app,这都是在一个内部循环中,它做了很多简单的native + - *^ =操作,不用作函数参数或任何东西.
我正在制作一个内存块复制例程,需要以高效的块处理原始内存块.我的问题不是关于我正在制作的专门复制例程,而是关于如何正确检查C中的原始指针对齐.
我有一个内存的原始指针,让我们说它已经被转换为非空的char*.在我的架构中,当它与64字节块相对应时,我可以非常高效地以64字节块的形式复制内存.所以(标准)技巧是我将在头部和/或尾部"手动"执行0-63字节的简单复制,以将副本从任意长度的任意字符*转换为具有某些倍数的64字节对齐指针长度为64个字节.
现在的问题是,你如何合法地"检查"一个指针来确定(和操纵)它的对齐?显而易见的方法是将其转换为整数并检查位:
char *pointer=something.
int p=(int)pointer;
char *alignedPointer=(char *)((p+63)&~63);
Run Code Online (Sandbox Code Playgroud)
注意这里我意识到alignedPointer并没有指向与指针相同的内存......这是我可以称之为高效复制例程的"向上舍入"指针,我将手动处理任何其他字节.
但是编译器(理所当然地)将指针转换为整数.但是我怎样才能检查和操纵LEGAL C中指针的低位?理想情况下,对于不同的编译器,我不会得到任何错误或警告.
我有一个应用程序,通过250 MB的数据流,应用一个简单快速的神经网络阈值函数到数据块(每个只有2个32位字).基于(非常简单的)计算的结果,块被不可预测地推入64个箱中的一个.所以这是一个大流和64个较短(可变长度)的流.
使用不同的检测功能重复多次.
计算是内存带宽有限.我可以说这是因为即使我使用的计算密集程度更高的判别函数也没有速度变化.
构造新流的写入以优化内存带宽的最佳方法是什么?我特别认为理解缓存使用和缓存行大小可能在这方面发挥重要作用.想象一下最糟糕的情况,我有64个输出流,运气不好,许多映射到同一个缓存行.然后,当我将下一个64位数据写入流时,CPU必须将过时的高速缓存行清除到主存储器,然后加载到正确的高速缓存行中.每个都使用64 BYTES的带宽...所以我的带宽有限的应用可能会浪费95%的内存带宽(尽管在这个假设的最坏情况下).
甚至很难尝试测量效果,因此围绕它设计方法更加模糊.或者我甚至追逐一个幽灵瓶颈,以某种方式硬件优化得比我更好?
我正在使用Core II x86处理器,如果这有任何区别的话.
编辑:这是一些示例代码.它通过一个数组流,并将其元素复制到伪随机选择的各种输出数组.使用不同数量的目标bin运行相同的程序会产生不同的运行时,即使完成了相同数量的计算和内存读写操作:
2个输出流:13秒
8个输出流:13秒
32个输出流:19秒
128个输出流:29秒
512个输出流:47秒
使用512与2输出流之间的差异是由缓存行驱逐开销引起的4倍(可能是??).
#include <stdio.h>
#include <stdlib.h>
#include <ctime>
int main()
{
const int size=1<<19;
int streambits=3;
int streamcount=1UL<<streambits; // # of output bins
int *instore=(int *)malloc(size*sizeof(int));
int **outstore=(int **)malloc(streamcount*sizeof(int *));
int **out=(int **)malloc(streamcount*sizeof(int));
unsigned int seed=0;
for (int j=0; j<size; j++) instore[j]=j;
for (int i=0; i< streamcount; ++i)
outstore[i]=(int *)malloc(size*sizeof(int));
int startTime=time(NULL);
for (int k=0; k<10000; k++) {
for (int i=0; i<streamcount; i++) out[i]=outstore[i]; …Run Code Online (Sandbox Code Playgroud) 我正在实现一个基数树/ patricia trie(无论你想要什么叫它).我想在一个严重不足的硬件上使用它在字典中进行前缀搜索.它应该或多或少地像自动完成一样工作,即显示键入的前缀匹配的单词列表.
我的实现基于这篇文章,但其中的代码不包括前缀搜索,尽管作者说:
[...]假设您要枚举所有具有公共前缀"AB"的键的节点.您可以从该根开始执行深度优先搜索,每当遇到后边时停止.
但是我不明白这是怎么回事.例如,如果我从这些单词构建基数树:
疾病
虚构的
想象力
想象 立即
模仿 立即 巨大 的
对于前缀"i"和"in",我将得到完全相同的"最佳匹配",这样我就很难通过从最佳匹配中遍历树来收集所有匹配的单词.
此外,Java中的基数树实现在RadixTreeImpl.java中具有已实现的前缀搜索.该代码显式检查所有节点(从某个节点开始)的前缀匹配 - 它实际上比较了字节.
有人能指出我在基数树上实现前缀搜索的详细描述吗?Java实现中使用的算法是唯一的方法吗?
是否有编译器或独立预处理器,它采用C++文件并运行模板扩展传递,生成具有扩展模板实例的新C++代码?
我记得90年代中期这样一个工具,当模板仍然是新的和实验性的时候,预处理器是一种在没有本机模板支持的情况下使用编译器进行模板编程的方法.
这比宏处理步骤复杂得多,因为它可能需要解析和标记代码以理解上下文.
我希望在编写OpenCL代码时使用这样的工具. OpenCL是C++,但不支持模板.我希望我可以编写模板,甚至是简单的模板,比如整数或bool唯一的参数,并且有一些工具预先解析文件并通过查找模板的使用并扩展调用并给我新的C++代码OpenCL编译器可以理解.
即使是非常有限的工具也可能有用,它不需要支持每个模板的怪癖,甚至不需要支持多个模块或任何东西.
替代方案:#define宏到处都是..丑陋,不安全,效率低下,用途不多.
我有自己的多线程C程序,可以根据CPU内核的数量平滑地扩展速度.我可以用1,2,3等线程运行它并获得线性加速..在6核上最高可达5.5x速度Ubuntu Linux机器上的CPU.
我有机会在一个非常高端的Sunfire x4450上运行该程序,其中包含4个四核Xeon处理器,运行Red Hat Enterprise Linux.我急切期待看到16个内核以16个线程运行我的程序的速度有多快..但它的运行速度与两个线程相同!
稍后进行了大量的拔毛和调试,我发现我的程序确实在创建所有线程,它们实际上是同时运行的,但是线程本身比它们应该更慢.2个线程的运行速度比1快1.7倍,但是3个,4个,8个,10个,16个线程的运行速度仅为1.9倍!我可以看到所有线程都在运行(没有停滞或睡眠),它们只是很慢.
为了检查硬件是否有问题,我同时独立地运行了我的程序的第六个副本.他们全速奔跑.真的有16个内核,它们确实全速运行,并且确实有足够的RAM(实际上这台机器有64GB,而且每个进程只使用1GB).
所以,我的问题是,是否有一些操作系统解释,也许是一些每进程资源限制,它自动缩减线程调度,以防止一个进程占用机器.
线索是:
发生了什么?是否有一些进程CPU限制策略?如果是这样我怎么测量呢?还有什么可以解释这种行为?
感谢您的解决方案,2010年的伟大至强减速之谜!