Tag: 优化

如何使用Dot产品获得峰值CPU性能?

问题 我一直在研究HPC,特别是使用矩阵乘法作为我的项目(参见我在配置文件中的其他post)。 我在那些方面取得了不错的成绩,但还不够好。 我退后一步看看我能用点积计算做得多好。 点乘积与矩阵乘法 点积更简单,我可以在不处理打包和其他相关问题的情况下测试HPC概念。 缓存阻塞仍然是一个问题,这是我的第二个问题。 算法 将两个double数组A和B n相应元素相乘并求它们。 assembly中的double点产品只是一系列movapd , mulpd , addpd 。 以巧妙的方式展开和排列,可以使movapd / mulpd / addpd组在不同的xmm寄存器上运行,因此是独立的,优化了流水线操作。 当然,事实certificate,这与我的CPU无序执行无关。 还要注意,重新安排需要剥离最后一次迭代。 其他假设 我不是在编写通用点积的代码。 代码是针对特定尺寸的,我不处理边缘情况。 这只是为了测试HPC概念并查看我可以获得的CPU使用类型。 结果 编译为gcc -std=c99 -O2 -m32 -mincoming-stack-boundary=2 -msse3 -mfpmath=sse,387 -masm=intel 。 我和平时不同的电脑。 这台计算机有一个i5 540m ,在两步Intel Turbo Boost之后, 2.8 GHz * 4 FLOPS/cycle/core = 11.2 GFLOPS/s per core可以获得2.8 GHz * […]

最少组装或编译至少三个值

我正在查看GCC-4.8为x86_64生成的代码,并想知道是否有更好(更快)的方法来计算三个值的最小值。 这是Python的集合模块的摘录,它计算m , rightindex+1和leftindex的最小值: ssize_t m = n; if (m > rightindex + 1) m = rightindex + 1; if (m > leftindex) m = leftindex; GCC使用CMOV生成连续相关的代码: leaq 1(%rbp), %rdx cmpq %rsi, %rdx cmovg %rsi, %rdx cmpq %rbx, %rdx cmovg %rbx, %rdx 是否有更快的代码可以通过删除数据依赖性来利用处理器无序并行执行? 我想知道是否存在用于计算多个值的最小值而不使用条件或谓词指令的已知技巧。 我也想知道是否有一些饱和的算术内在函数可以帮助解决这种情况。 EDITS: 如图所示,代码使用带符号的算术,但无符号算术答案也会有所帮助。 我询问了最少三个,但也对n最小的n感兴趣。 Linus对CMOV的警告: http : //ondioline.org/mail/cmov-a-bad-idea-on-out-of-order-cpus

难以衡量C / C ++性能

我写了一段C代码,以展示关于优化和分支预测的讨论中的一点。 然后我注意到比我预期的更多样化的结果。 我的目标是用C ++和C之间通用子集的语言编写它,这对于两种语言都是标准兼容的并且相当便携。 它在不同的Windows PC上进行了测试: #include #include /// @return – time difference between start and stop in milliseconds int ms_elapsed( clock_t start, clock_t stop ) { return (int)( 1000.0 * ( stop – start ) / CLOCKS_PER_SEC ); } int const Billion = 1000000000; /// & with numbers up to Billion gives 0, 0, […]

为什么GCC保持空function?

在大多数情况下,如果我想在C中创建一个可选function,我只需创建两个这样的函数: #ifdef OPTIONAL_SOMETHING void do_something(int n, const char *s) { while (n–) { printf(“%s”, s); } /* …You might get the point, really do something… */ } #else void do_something(int n, const char *s) { /* Empty body */ } #endif 因此,如果符号未定义 – 禁用该function时 – 将空函数编译到可执行文件中。 深入研究汇编列表,似乎GCC 在禁用优化时编译并调用空函数。 如果启用了优化 ,也使用了-O2和-O3 ,它只编译必要的堆栈处理代码,但它会优化调用指令。 总而言之,它保留了function。 大约相同的情况适用于非空但未使用的方法。 它应该简单地扔掉整个东西,但事实并非如此。 为什么它是默认行为? […]

取C中两个有符号数的平均值

让我们说我们有x和y,两者都是C中的有符号整数,我们如何找到两者之间最准确的平均值? 我更喜欢一种不利用任何机器/编译器/工具链特定工作的解决方案。 我提出的最好的是: (a / 2) + (b / 2) + !!(a % 2) * !!(b %2)是否有更准确的解决方案? 快点? 更简单? 如果我们知道一个是否比其他先验大? 谢谢。 d 编者注 :请注意,当输入值接近C int类型的最大绝对边界时,OP期望答案不受整数溢出的影响。 这在原始问题中没有说明,但在给出答案时很重要。

了解有关i ++和i = i + 1的更多信息

我想知道两种增量forms之间是否存在差异。 一些链接说i ++比i = i + 1更快; 另外作为人之一,我的观察对于汇编代码也是一样的。 请检查图像,其中汇编代码对于i ++和i = i + 1都是相同的 – 还有另一个链接说以前曾经是真的,增量运算符比加法和赋值更快,但现在编译器优化i ++和i = i + 1相同。 是否有任何官方文件/文件我们可以参考确认什么是正确的? (我通常会使用信用卡和一个人在stackoverflow上接受的答案数量。在我提供的链接上找不到任何此类信息)。

为什么这个NodeJS比本机C快2倍?

为了在工作中进行演示,我想比较NodeJS和C的性能。这是我写的: Node.js(for.js): var d = 0.0, start = new Date().getTime(); for (var i = 0; i > 1; } var end = new Date().getTime(); console.log(d); console.log(end – start); C(for.c) #include #include int main () { clock_t start = clock(); long d = 0.0; for (long i = 0; i > 1; } clock_t end = […]

如何在CUDA中使用uint4向量正确转换全局内存数组以增加内存吞吐量?

通常有两种技术可以在计算能力1.3 GPU上增加CUDA内核上全局内存的内存吞吐量。 内存访问合并并访问至少4个字节的字。 利用第一种技术,通过相同半翘曲的线程对相同存储器段的访问被合并为更少的事务,而在访问至少4字节的字时,该存储器段有效地从32字节增加到128。 更新:基于talonmies回答的解决方案 。 当存在全局存储器中存在无符号字符时,要访问16字节而不是1字节字,通常通过将存储器arrays转换为uint4来使用uint4向量。 要从uint4向量中获取值,可以将其重新编译为uchar4,如下所示: #include #include #include __global__ void kernel ( unsigned char *d_text, unsigned char *d_out ) { int idx = blockIdx.x * blockDim.x + threadIdx.x; extern __shared__ unsigned char s_array[]; uint4 *uint4_text = reinterpret_cast(d_text); uint4 uint4_var; //memory transaction uint4_var = uint4_text[0]; //recast data to uchar4 uchar4 c0 = *reinterpret_cast(&uint4_var.x); […]

在C中声明函数内的结构

我有一个只有一个函数必须访问的结构。 该函数将诸如“k,K,kb,KB,m,M,mb,MB,…”之类的标记转换为实际单位。 这样做的目的是简化配置文件。 所以,假设我们有: static uint32_t real_unit(const char *str) { struct u2type { char key[3]; uint32_t val; } const u2types[] = { { “k”, KB_UNIT }, { “K”, KB_UNIT }, { “kb”, KB_UNIT }, { “KB”, KB_UNIT }, { “m”, MB_UNIT }, { “M”, MB_UNIT }, { “mb”, MB_UNIT }, { “MB”, MB_UNIT }, { […]

局部变量初始化是否必须?

对于那些做过一些c / c ++维护或增强的人来说,未经初始化的本地人所造成的维护问题(特别是指针)将是显而易见的,但我仍然会看到它们并偶尔听到性能影响作为其理由。 在c中很容易certificate冗余初始化已经过优化: $ less test.c #include main() { #ifdef INIT_LOC int a = 33; int b; memset(&b,66,sizeof(b)); #else int a; int b; #endif a = 0; b = 0; printf (“a = %i, b = %i\n”, a, b); } $ gcc –version gcc (GCC) 3.4.4 (cygming special, gdc 0.12, using dmd 0.125) […]