Tag: 性能

C中最快的去交织操作?

我有一个指向mixed字节数组的指针,它包含两个不同数组array1和array2的交错字节。 mixed看起来像这样: a1b2c3d4… 我需要做的是解交织字节,所以我得到array1 = abcd…和array2 = 1234… 我知道提前mixed的长度,并且array1和array2的长度是等价的,都等于mixed / 2 。 这是我当前的实现(已分配array1和array2 ): int i, j; int mixedLength_2 = mixedLength / 2; for (i = 0, j = 0; i < mixedLength_2; i++, j += 2) { array1[i] = mixed[j]; array2[i] = mixed[j+1]; } 这避免了任何昂贵的乘法或除法运算,但仍然运行得不够快。 我希望有一些像memcpy这样的东西,它可以使用一个可以使用低级块复制操作的索引器来加速这个过程。 是否有比我现有的更快的实施? 编辑 目标平台是针对iOS和Mac的Objective-C。 对于iOS设备而言,快速操作更为重要,因此针对iOS的解决方案将比没有更好。 更新 感谢大家的回应,尤其是Stephen Canon,Graham Lee和Mecki。 […]

转置2Darrays

你如何有效地转置矩阵? 是否有这样的库,或者你会使用什么算法? 例如: short src[W*H] = { {1,2,3}, {4,5,6} }; short dest[W*H]; rotate_90_clockwise(dest,src,W,H); //<– magic in here, no need for in-place //dest is now: { {4, 1}, {5, 2}, {6, 3} }; (在我的具体情况下,它的src数组是原始图像数据,目标是帧缓冲,我在ARM上嵌入了不支持汇编的工具链)

浮点乘法执行速度较慢,具体取决于C中的操作数

我正在对以前从文件中读取的矩阵执行模板计算。 我使用两种不同的矩阵(NonZero类型和Zero类型)。 两种类型共享边界的值(通常为1000),而其余元素对于零类型为0,对于NonZero类型为1。 该代码将文件的矩阵存储在两个相同大小的分配矩阵中。 然后,它使用自己的值和邻居值(添加x 4和mul x 1)在一个矩阵的每个元素中执行操作,并将结果存储在第二个矩阵中。 一旦计算完成,交换矩阵的指针并且执行相同的操作有限次数。 在这里你有核心代码: #define GET(I,J) rMat[(I)*cols + (J)] #define PUT(I,J) wMat[(I)*cols + (J)] for (cur_time=0; cur_time<timeSteps; cur_time++) { for (i=1; i<rows-1; i++) { for (j=1; j<cols-1; j++) { PUT(i,j) = 0.2f*(GET(i-1,j) + GET(i,j-1) + GET(i,j) + GET(i,j+1) + GET(i+1,j)); } } // Change pointers for next iteration auxP […]

C:动态分配数组的memcpy速度

我需要有关以下代码性能的帮助。 它对两个任意大小的动态分配数组执行memcpy: int main() { double *a, *b; unsigned n = 10000000, i; a = malloc(n*sizeof(double)); b = malloc(n*sizeof(double)); for(i=0; i<n; i++) { a[i] = 1.0; /* b[i] = 0.0; */ } tic(); bzero(b, n*sizeof(double)); toc("bzero1"); tic(); bzero(b, n*sizeof(double)); toc("bzero2"); tic(); memcpy(b, a, n*sizeof(double)); toc("memcpy"); } tic / toc测量执行时间。 在我的电脑上,memcpy需要0.035秒(Linux,gcc版本4.4.6)。 如果我现在取消注释初始化目标数组b的行,则代码快三倍(!) – 0.011s。 我在使用循环而不是memcpy时观察到类似的行为。 通常我不关心这个,因为它足以在使用之前“初始化”内存。 […]

为什么在工作交错时TCP写入延迟会更糟?

我一直在分析TCP延迟(特别是从用户空间到小消息的内核空间的write ),以便对write的延迟有所了解(确认这可能是特定于上下文的)。 我注意到测试之间存在很大的不一致,这对我来说似乎很相似,而且我很想知道差异来自何处。 我知道微基准测试可能会有问题,但我仍然觉得我缺少一些基本的理解(因为延迟差异是~10倍)。 设置是我有一个C ++ TCP服务器接受一个客户端连接(来自同一CPU上的另一个进程),并且在与客户端连接时进行20次系统调用以write套接字,一次发送一个字节。 服务器的完整代码将在本文末尾复制。 这是使用boost/timer每次write时间输出(增加~1 mic的噪声): $ clang++ -std=c++11 -stdlib=libc++ tcpServerStove.cpp -O3; ./a.out 18 mics 3 mics 3 mics 4 mics 3 mics 3 mics 4 mics 3 mics 5 mics 3 mics … 我可靠地发现第一次write明显慢于其他write 。 如果我在一个计时器中包装10,000个write调用,则每次write的平均值为2微秒,但第一个调用始终是15个以上的麦克风。 为什么会出现这种“升温”现象? 相关地,我运行了一个实验,在每个write调用之间我做了一些阻止CPU工作(计算一个大的素数)。 这会导致所有 write调用都很慢: $ clang++ -std=c++11 -stdlib=libc++ tcpServerStove.cpp -O3; ./a.out 20 mics 23 […]

在C数组中进行按位运算的最有效方法是什么

我有一个C数组,如: char byte_array[10]; 另一个充当面具: char byte_mask[10]; 我想在每个字节上获得另一个数组,该数组是第一个数据加上第二个使用按位运算的结果。 最有效的方法是什么? 谢谢你的回答。

如何在大多数平台上使用C99标准类型以实现最大的可移植性和效率?

首先,这是我理解并思考问题的真实情况。 对单个变量(如计数器或循环索引)使用快速数据类型。 例如: #define LOOP_COUNT (100U) uint_fast8_t index; for(index = 0; index < LOOP_COUNT; index++){ /* Do something */ } 我想这里最合适的类型是uint_fast8_t因为index永远不会超过255,这将是所有平台上最快的实现。 如果我使用unsigned int代替它,它将在> = 16位平台中最快,但在<16位平台中将更慢,因为int是标准的最小16位。 此外,如果我使用uint8_t ,它将在> 8位平台上变慢,因为编译器添加AND 0xFF指令来检查每个增量的溢出(我的ARM7编译器甚至在全速优化时也这样做)。 size_t也不是一个选项,因为它可能大于本机整数大小。 如果预计8位溢出,那么这边是坏的(?),它就不会发生。 程序员应该手动检查溢出(因为他/她应该恕我直言),这可能会导致错误的代码,如果忘记。 此外,如果LOOP_COUNT在8位平台上“意外”设置为大于255的值,编译器(甚至PC-Lint让我惊讶)也不会发出任何警告/问题,但警告将在8位平台上生成,这将降低可移植性并引入错误,但这可以通过#if检查来避免。 如果像数组或结构中那样关注内存使用情况,请尽可能使用最少的数据类型。 例如: uint_least8_t array[100]; 如果关注内存使用情况,它是最便携,最有效的声明数组的方法。 如果平台上可以进行字节访问,则此类型将提供字节数组,否则将提供最小的可访问宽度整数数组。 此外,如果我们有结构数组,则可以在结构中使用最少类型。 最小类型也可能遇到快速类型的问题,因为对于这两种情况,可以在不同平台上改变变量的宽度。 尽可能避免使用固定宽度的数据类型,因为在某些平台上它们甚至可能不存在,除了硬件寄存器访问,通信协议映射等,我们需要知道变量的确切位。 例如: typedef struct { uint8_t flags; uint8_t length; uint8_t data[100]; uint16_t crc; } […]

R:使用带有.Call和C / C ++包装器的Fortran子例程代替.Fortran的优点?

我有一个R包,它使用大量的Fortran子程序来进行递归线性代数计算的嵌套循环(严重依赖于BLAS和LAPACK例程)。 作为Fortran的接口,我使用.Fortran函数。 我刚刚阅读了Jonathan Callahan关于在C / C ++编写的子程序中使用.Call而不是.C 的博客文章 ,它让我觉得在使用Fortran子程序时,通过写一个简单的方法也可以更好地使用.Call接口C中的包装器然后调用Fortran子例程? 如上所述,我的Fortran代码非常简单,因为我只使用double或integer类型的多维数组。 但是我已经知道我必须在R端编写相当多的检查以确保一切都不会崩溃,因为我不小心忘记将某些矩阵的存储模式更改为整数或某些矩阵的维度已更改等。 子程序写为F90 / 95。

在ruby进程之间使用大型数据对象

如果使用Marshal.dump写入文件,我有一个大约10兆字节的Ruby哈希。 在gzip压缩之后它大约是500千字节。 迭代和更改此哈希在ruby中非常快(毫秒的分数)。 即使复制它也非常快。 问题是我需要在Ruby on Rails进程之间共享此哈希中的数据。 为了使用Rails缓存(file_store或memcached)执行此操作,我首先需要Marshal.dump文件,但是在序列化文件时会产生1000毫秒的延迟,在序列化时会产生400毫秒的延迟。 理想情况下,我希望能够在100毫秒内从每个进程保存和加载此哈希。 一个想法是生成一个新的Ruby进程来保存这个哈希,为其他进程提供API来修改或处理其中的数据,但我想避免这样做,除非我确定没有其他方法可以共享这个对象很快。 有没有一种方法可以更直接地在进程之间共享此哈希,而无需序列化或反序列化它? 这是我用来生成类似于我正在使用的哈希的代码: @a = [] 0.upto(500) do |r| @a[r] = [] 0.upto(10_000) do |c| if rand(10) == 0 @a[r][c] = 1 # 10% chance of being 1 else @a[r][c] = 0 end end end @c = Marshal.dump(@a) # 1000 milliseconds Marshal.load(@c) # 400 milliseconds 更新: […]

使用C中的预取和缓存优化对arrays的线性访问

披露:我在programmers.stack上尝试过类似的问题,但那个地方离活动堆栈还差不多。 介绍 我倾向于使用大量的大图像。 它们也有多个序列,必须重复处理和播放。 有时候我使用GPU,有时候是CPU,有时候都是。 大多数访问模式本质上是线性的(来回),让我思考有关数组的更基本的事情,以及如何编写代码优化以在给定硬件上实现最大内存带宽(允许计算不阻塞读/写) 。 测试规格 我在2011年MacbookAir4,2(I5-2557M)上使用4GB RAM和SSD完成了这项工作。 除了iterm2之外,在测试期间没有其他任何东西在运行。 gcc 5.2.0(自制)带标志: -pedantic -std=c99 -Wall -Werror -Wextra -Wno-unused -O0带有额外的include和库标志以及框架标志,以便使用我倾向于使用的glfw计时器。 我可以在没有的情况下完成它,没关系。 当然,所有64位。 我已经尝试使用可选的-fprefetch-loop-arrays标志进行测试,但它似乎根本没有影响结果 测试 在堆上分配两个n bytes数组 – 其中n是8, 16, 32, 64, 128, 256, 512 and 1024 MB 一次将array初始化为0xff ,字节 测试1 – 线性拷贝 线性副本: for(uint64_t i = 0; i < ARRAY_NUM; ++i) { array_copy[i] = array[i]; […]