我需要将文件的文件大小超过2 GB的大小. (在4.6 GB文件上进行测试).没有外部程序可以做到这一点? 当前状态: filesize(),stat()和fseek()失败 fread()和feof()作品 有可能通过阅读文件内容(极慢!)来获取文件大小. $size = (float) 0; $chunksize = 1024 * 1024; while (!feof($fp)) { fread($fp, $chunksize); $size += (float) $chunksize; } return $size; 我知道如何在64位平台上获取它(使用fseek($fp, 0, SEEK_END)和ftell()),但是我需要32位平台的解决方案. 解决方案:我已经开始为此开源项目. 大文件工具 大文件工具是一系列hacks的集合,这些骇客是在PHP中操纵文件超过2 GB(即使在32位系统上)的收集. 答案:
以下是关于 x86 的编程技术问答
我正在尝试使用Intel®PerformanceCounter Monitor(PCM)工具来测量NIC设备的PCIE带宽.但是,我无法理解它的输出. 为了测量PCIE带宽,我执行了二进制PCM-IIO.该二进制有助于测量每个PCIE设备的监视器PCIE带宽.执行二进制后,我得到以下输出. |IIO Stack 2 - PCIe1 |IB write|IB read|OB read|OB write|TLB Miss|VT-d L3 Miss|VT-d CTXT Miss|VT-d Lookup| |_____________________________|________|_______|_______|________|________|____________|______________|___________| | Part0 (1st x16/x8/x4) |4498 M |9003 M | 0 |3256 K |
我有一台旧的PC. 我想准确计算其处理器的MIPS(每秒百万个说明). 我该怎么办? 解决方案 与您想要的内容一致,以下是一些引导程序代码,该代码可以执行一种可能以某种方式测量MIP的基准.这里的主要目标是低级,我相信这是您可以实际使用PC编程的最低级别,除非您愿意更换BIOS或其他东西. 无论如何,这是软盘映像的代码,当启动时,它将尝试执行四个指令(两个add s,一个sub和一个有条件的跳跃)一百万次.执行指令的次数由ITERS宏控制.通过提高或降低它,您可以指定应该进行多少迭代. 时间是通过使用rdtsc指令来衡量的,该指令返回自动加速自动滴度以来为64位edx和eax的处理器数量.通过在执行循环之前和之前计算此值的差异,我们将获得处理器执行它的刻度数量.然后,通过将BIOS 10H调用作为十六进制值输出到屏幕上.显然,在其上花费的实际时间取决于处理器时钟的频率. 这是来源.如果使用-f bin进行NASM进行编译,则将获得软盘图像,然后使用某些RAW
我注意到,如果我们知道控制流的可能性很大,或者是错误的,我们可以告诉编译器,例如,在Linux内核中,有很多likely unlikely,实际上是由由gcc提供,所以我想找出它的工作原理,然后检查那里的组件: 20:branch_prediction_victim.cpp **** if (array_aka[j] >= 128) 184 .loc 3 20 0 is_stmt 1 185 00f1 488B85D0 movq -131120(%rbp), %rax 185 FFFDFF 186 00f8 8B8485F0 movl -131088(%rbp,%rax,4), %eax 186 FFFDFF 187 00ff 83F87F cmpl $127, %eax
我有一个非原子的62位双double,它会定期在一个线程中递增.此访问不需要原子.但是,此变量偶尔会由另一个线程读取(未编写).如果我对64位边界上的变量对齐,则读取为原子. 但是,有什么办法可以确保在增量期间不会读取变量?我可以调用序列管道或其他内容的CPU指令吗?记忆障碍? 我想到在关键线程中宣布变量原子并使用std::memory_order::memory_order_relaxed(以及稀有线程中更严格的内存屏障),但似乎同样昂贵. 解决方案 由于您标记了x86,这将是x86特定的. 增量本质上是三个部分,读,添加,写作.增量不是原子质,但是只要变量不超过缓存线边界,这三个步骤(我想不计算出来,无论如何都不是可观察到的)在自然的对齐状态下,正如P6一样,在必须对齐四词之前). . 因此您已经无法读取撕裂的值.您能做的最糟糕的是覆盖它在读取的时刻和新值写的瞬间之间,但是您只是在阅读.
我的CPU是Ivybridge. 我的意思是,让我们考虑一下Agner的FOG Optimizing_Assembly的示例. 12.6章和12.10a示例: movsd xmm2, [x] movsd xmm1, [one] xorps xmm0, xmm0 mov eax, coeff L1: movsd xmm3, [eax] ; c[i] mulsd xmm3, xmm1 ; c[i]*x^i mulsd xmm1, xmm2 ; x^(i+1) addsd xmm0, xmm3 ; sum += c[i]*x^i add eax, 8 cmp eax, coeff_end jb L1 ,前端不是瓶颈(这很明显,因为乘法的延迟). 我们有两个循环依赖性(我跳过add eax, 8): 1
我不知道任何真正的组装,但是可以读取GCC -S输出以评估给定C代码的实际成本. 这个问题不是关于分析和基准的太多,而是教育意义.我需要有人向我解释为什么[1]片段不比第二个摘要快. 好吧,曾经想到:"是的,像MUL这样的某些操作非常昂贵,但是如果一个组件比另一个组件大于另一个组件,则应该慢一点". 这是真的,直到我遇到了这两个: unsigned char bytes[4] = {0, 0, 0, 5}; // 1 int32_t val = *((int32_t*)bytes); /* produces: leaq -16(%rbp), %rax movl (%rax), %eax movl %eax, -4(%rbp) movl $0, %eax */ // 2 val = bytes[3] |
在此Web链接中: http://www.7-cpu.com/cpu/cpu/ivybridge..html 说Ivy Bridge L1缓存访问的延迟是: l1数据缓存延迟= 4个循环,用于通过指针进行简单访问 l1数据缓存延迟= 5个循环,用于使用复杂地址计算(size_t n, *p; n = p [n]). 而不是"简单",它们是否意味着指针大小与单词大小相同?因此,如果指针为32位,它是32位OS,那么这将是"简单"的,否则会花费"复杂"潜伏期? 我只是不太了解他们对两个潜伏期的差异的解释. 解决方案 完整的x86有效地址看起来像displacement + base + index * scale(其中displacement是常数,base和index是寄存器,scale是1、2、4或8). 如果仅存在displacement(或者也许是base术语),他们听起来很简单,而拥有index * scale则肯定会属于复杂类别.
我目前正在构建来自来源的软件,这对我来说至关重要.因此,我想优化它以在我的特定Intel CPU上运行.建筑过程要求我设置-March和-mtune标志. 如果在我的处理器节点上我使用 gcc -march=native -Q --help=target|grep march gcc -mtune=native -Q --help=target|grep mtune 我获得了3月的" core-avx2"和mtune的"通用".但是 cat /proc/cpuinfo 我得到: processor : 23 vendor_id : GenuineIntel cpu family : 6 model : 63 model name : Intel(R) Xeon(R) CPU E5-2670 v3 @ 2.30GHz stepping : 2 microcode : 0x3d cpu MHz : 2599.993 c
从32位CPU模式开始,有可用于X86体系结构的扩展地址操作数.一个人可以指定基础地址,位移,索引寄存器和缩放系数. 例如,我们想大步浏览32位整数的列表(每两个都来自32字节长的数据结构的数组,%rdi作为数据索引,%rbx作为基本指针). addl $8, %rdi # skip eight values: advance index by 8 movl (%rbx, %rdi, 4), %eax # load data: pointer + scaled index movl 4(%rbx, %rdi, 4), %edx # load data: pointer + scaled index + displacement 我知道,这种复杂的解决方案适合单个机器代码指令.但是,这种操作的成本是多少?与独立指针计算相比,它与之相比如何: addl $32, %rbx # skip eight values
让我们交换2个变量. int temp = a; a = b; b = temp; 这是一些半优化的ASM伪代码: mov eax, dword ptr [rbp+4] mov ebx, dword ptr [rbp+8] mov dword ptr [rbp+8], eax mov dword ptr [rbp+4], ebx 与彼此的对象相关的速度会更快吗? a ^= b ^= a ^= b; asm psuedocode: mov eax, dword ptr[rbp+4] xor eax, dword ptr[rbp+8] xor dword ptr[rbp+8], eax xor eax, dword ptr[rbp+8] xor dword ptr[rbp+8], eax mov eax, dword ptr[rbp+4] 其中哪一个会更快? (欢迎来宾) 解决方案 将其拉入两个寄存器,然后向后写交换内容可能是解决方案中最快的.
Skylakex(Agner Fog的指令表): +-----------------------+-------------+-------------------+---------------------+----------------+---------+-----------------------+ | Instruction | Operands | µops fused domain | µops unfused domain | µops each port | Latency | Reciprocal throughput | +-----------------------+-------------+-------------------+---------------------+----------------+---------+-----------------------+ | VGETMANTPS/PD
tl; dr :我有两个与clang编译的功能等效的C代码(事实是C代码无关紧要;我认为只有大会很有趣),而IACA告诉我应该更快的速度,但我不明白为什么,我的基准测试对这两个代码显示相同的性能. 我有以下C代码(ignore #include "iacaMarks.h",IACA_START,IACA_END暂时): ref.C: #include "iacaMarks.h" #include #define AND(a,b) _mm_and_si128(a,b) #define OR(a,b) _mm_or_si128(a,b) #define XOR(a,b) _mm_xor_si128(a,b) #define NOT(a) _mm_andnot_si128(a,_mm_set1_epi32(-1)) void sbox_ref (__m128i r0,__m128i r1,__m128i r2,__m128i r3
给定 virtual 之间的分离来处理操纵的处理和代表内存中实际位置的物理地址,您可以播放一些有趣的技巧:例如创建a 在分配空间的起点/结束时毫无连续的圆形缓冲区. 我想知道此类映射技巧在情况下是否对数据读取或写入访问受惩罚: 对物理页面的访问主要是通过相同的虚拟映射,但偶尔通过其他映射(S). 对物理页面的访问或多或少在映射到同一物理地址的虚拟地址之间或多或少均匀分布. 我尤其对过去十年左右发布的X86芯片感兴趣,但也对现代手臂和电力芯片感兴趣. 解决方案 80x86(我不知道其他架构): a)正常的指令/数据/统一的缓存是物理索引的(因此不受分页技巧的影响) b)TLB实际上是索引的.这意味着(取决于很多事情),对于您的循环缓冲措施,您可能会期望没有圆形缓冲技巧的TLB错过.可能重要的事情包括面积的大小和所使用的TLB条目的类型数量(4 KIB,2 MIB/1 GIB);如果CPU预购TLB条目(最近的CPU DO),并且花费了足够的时间进行其
我只是在运行一个while 1循环,并测量缓存失误. int main() { while(1); } 此特定过程与一个CPU(使用任务集)绑定,并且该CPU是隔离的,这意味着没有其他过程可以安排在同一CPU上.现在,我开始使用perf来测量缓存性能,令我惊讶的是,最后一级高速缓存失误是42%. 22,579 cache-references (20.82%) 8,976 **cache-misses # 39.754 %** of all cache refs (20.83%) 4,414 **LLC-load-misses # 42.74%** of all LL-cache hits 我感到惊讶,我希望零缓存失误,因为我没有进行任何内存操作.对此的任何帮助/想法. CPU:型号名称:Intel(R)
我有一个我正在使用_mm_prefetch()的课程,以预先要求double类型的cacheline包含一个类成员: class MyClass{ double getDouble(){ return dbl; } //other members double dbl; //other members }; _mm_prefetch() 签名是: void _mm_prefetch (char const* p, int i) 但是当我这样做时: _mm_prefetch((char*)(myOb.getDouble()), _MM_HINT_T0); GCC抱怨: 错误:从类型'double'到类型'char*' 的铸件无效 那么我如何预摘此类成员? 解决方案 如果您从链接到它的网站中读取了_mm_prefetch()的描述: void _mm_prefetch (char
显然,当大小很重要时,应使用固定宽度的积分类型. 但是,我阅读(Insomniac Games样式指南),当尺寸不重要时,应首选" int",用于循环计数器/函数args/return代码/ect-给出的基本原理是固定宽度类型可以排除某些编译器优化. 现在,我想区分"编译器优化"和"针对目标体系结构更合适的typedef".后者具有全球范围,除非编译器可以某种程度上理解该程序的全球性能,否则我的猜测可能会非常有限.前者具有本地范围,在该范围内,编译器将自由地根据本地寄存器压力/用法来优化使用的字节数,并且操作除其他外. 标准允许对非固定宽度类型的"编译器优化"(如我们所定义)吗?有什么好例子吗? 如果没有,并且假设CPU可以在较小类型的较小类型上运行,那么从性能的角度来看,我不会看到使用固定宽度整数根据本地上下文大小的损害.至少这有可能减轻寄存器压力,我认为不能更糟. 解决方案 经验法则是使用int的原因是,标准将此积分类型定义为CPU的自然数据类型(前提
试图优化有限差异代码所需的未对准读取的读取时,我更改了这样的未对准负载: __m128 pm1 =_mm_loadu_ps(&H[k-1]); 进入此对齐的读取 +洗牌代码: __m128 p0 =_mm_load_ps(&H[k]); __m128 pm4 =_mm_load_ps(&H[k-4]); __m128 pm1 =_mm_shuffle_ps(p0,p0,0x90); // move 3 floats to higher positions __m128 tpm1 =_mm_shuffle_ps(pm4,pm4,0x03); // get missing lowest float pm1 =_mm_move_ss(pm1,tpm1); // pack lowest float with 3 others 其中H是16个字节对齐; H[k+1],H[k±3]和movlhps&movhlps对H[k±2]的优化也有类
如何确定程序的CPE? 例如,我有此循环的汇编代码: # inner4: data_t = float # udata in %rbx, vdata in %rax, limit in %rcx, # i in %rdx, sum in %xmm1 1 .L87: # loop: 2 movss (%rbx,%rdx,4), %xmm0 # Get udata[i] 3 mulss (%rax,%rdx,4), %xmm0 # Multiply by vdata[i] 4 addss %xmm0, %xmm1 # Add to sum 5 addq $1, %rdx # Increment i 6 cmpq %rcx, %rdx