我有一个C数组,如:
char byte_array[10];
Run Code Online (Sandbox Code Playgroud)
另一个充当面具:
char byte_mask[10];
Run Code Online (Sandbox Code Playgroud)
我想在每个字节上获得另一个数组,该数组是第一个数据加上第二个使用按位运算的结果.
最有效的方法是什么?
谢谢你的回答.
假设我有一个类似以下的结构......
typedef struct {
int WheelCount;
double MaxSpeed;
} Vehicle;
Run Code Online (Sandbox Code Playgroud)
...我有一个这种类型的全局变量(我很清楚全局变量的缺陷,这是一个嵌入式系统,我没有设计,为此他们是一个不幸但必要的邪恶. )直接或通过指针访问结构成员是否更快?即
double LocalSpeed = MyGlobal.MaxSpeed;
Run Code Online (Sandbox Code Playgroud)
要么
double LocalSpeed = pMyGlobal->MaxSpeed;
Run Code Online (Sandbox Code Playgroud)
我的任务之一是简化和修复最近继承的嵌入式系统.
我注意到有时MSVC 2010根本没有重新排序SSE指令.我认为我不必关心循环中的指令顺序,因为编译器处理的最好,但似乎并非如此.
我该怎么想这个?什么决定最佳指令顺序?我知道某些指令具有比其他指令更高的延迟,并且某些指令可以在cpu级别上并行/异步运行.哪些指标与上下文相关?我在哪里可以找到它们?
我知道我可以通过剖析来避免这个问题,但是这些剖析器很昂贵(VTune XE)并且我想知道它背后的理论,而不仅仅是经验结果.
我也应该关心软件预取(_mm_prefetch)还是我可以假设cpu会比我做得更好?
可以说我有以下功能.我应该交错一些指令吗?我应该在流之前做商店,按顺序做所有的负载,然后做计算等......?我是否需要考虑USWC与非USWC,以及时间与非时间?
auto cur128 = reinterpret_cast<__m128i*>(cur);
auto prev128 = reinterpret_cast<const __m128i*>(prev);
auto dest128 = reinterpret_cast<__m128i*>(dest;
auto end = cur128 + count/16;
while(cur128 != end)
{
auto xmm0 = _mm_add_epi8(_mm_load_si128(cur128+0), _mm_load_si128(prev128+0));
auto xmm1 = _mm_add_epi8(_mm_load_si128(cur128+1), _mm_load_si128(prev128+1));
auto xmm2 = _mm_add_epi8(_mm_load_si128(cur128+2), _mm_load_si128(prev128+2));
auto xmm3 = _mm_add_epi8(_mm_load_si128(cur128+3), _mm_load_si128(prev128+3));
// dest128 is USWC memory
_mm_stream_si128(dest128+0, xmm0);
_mm_stream_si128(dest128+1, xmm1);
_mm_stream_si128(dest128+2, xmm2);;
_mm_stream_si128(dest128+3, xmm3);
// cur128 is temporal, and will be used next time, which …Run Code Online (Sandbox Code Playgroud) 有没有办法将PageSpeed(Google Chrome扩展程序)结果导出到文件中?我正在寻找一种方法,使用浏览器控制台中的PageSpeed选项卡从网站测试中导出结果.
optimization frontend google-chrome micro-optimization google-chrome-extension
在最新的 x86 架构上,存储到加载转发失败的成本是多少?
特别是,存储到加载转发会失败,因为加载部分与较早的存储重叠,或者因为较早的加载或存储跨越某些导致转发失败的对齐边界。
当然存在延迟成本:它有多大?是否还存在吞吐量成本,例如,失败的存储到加载转发是否使用了其他加载和存储甚至其他非内存操作无法使用的额外资源?
当存储的所有部分都来自存储缓冲区时,与混合存储缓冲区和 L1 的情况相比,是否有区别?
似乎有一个普遍的常识,即使用np.take速度比数组索引快得多。例如http://wesmckinney.com/blog/numpy-indexing-peculiarities/,快速numpy花式索引和Fast(er)numpy花式索引和缩减?。还有一些建议np.ix_在某些情况下更好。
我已经进行了一些分析,在大多数情况下,这似乎是正确的,尽管随着数组变大,差异会减小。
性能受阵列的大小,索引的长度(对于行)和采用的列数影响。行数似乎有最大的影响,即使索引为1D,数组中的列数也有影响。改变索引的大小似乎对方法之间的影响不大。
因此,问题有两个:1.为什么方法之间的性能会有如此大的差异?2.什么时候使用一种方法优于另一种方法?是否存在一些始终可以更好地工作的数组类型,顺序或形状?
有很多事情可能会影响性能,因此我在下面展示了其中的一些内容,并包括了用于尝试使其可再现的代码。
编辑我已经更新了图中的y轴,以显示值的完整范围。更清楚的是,差异小于一维数据的差异。
通过对比运行时间和行数,可以发现索引是相当一致的,并且有轻微的上升趋势。 take随着行数的增加,速度始终会变慢。

随着列数的增加,两者都会变慢,但take增加的幅度会更大(这仍然是一维索引)。

对于2D数据,结果相似。ix_还显示了使用情况,它似乎总体上具有最差的性能。

from pylab import *
import timeit
def get_test(M, T, C):
"""
Returns an array and random sorted index into rows
M : number of rows
T : rows to take
C : number of columns
"""
arr = randn(M, C)
idx = sort(randint(0, M, T))
return arr, idx
def draw_time(call, N=10, …Run Code Online (Sandbox Code Playgroud) 在下面突出显示的行中更改add为可adc显着提高性能。我觉得这很违反直觉,因为add有更多的端口要执行,而且它不依赖于标志。
CPU:英特尔 i7-9750H(Coffee Lake)。
UOPS_ISSUED.ANY add= ~2.87 uops /cycle。
UOPS_ISSUED.ANY adc= ~3.47 uops /cycle。
在这两种情况下,退休插槽是 98.5% 的 uops。
它反映在基准时间上,add版本要慢得多。
如果有人能帮助我理解为什么add变慢,我将不胜感激?我可以提供更多指标,只是不知道要寻找什么。
# Code to multiply large integer by a qword.
# RSI = input large integer (qword array).
# RDI = output large integer (qword array).
# RDX = qword to multiply the large integer by.
# ECX = number of 32-byte blocks to process (i.e. qwords …Run Code Online (Sandbox Code Playgroud) performance x86 assembly cpu-architecture micro-optimization
我有一个带有 2 个计数器的循环:i 和 j。如果它们具有相同的值 - 迭代的工作速度比它们的值不同时快得多:
Benchmark Mode Cnt Score Error Units
FloatsArrayBenchmark.times thrpt 20 341805.800 ± 1623.320 ops/s
FloatsArrayBenchmark.times2 thrpt 20 198764.909 ± 1608.387 ops/s
Run Code Online (Sandbox Code Playgroud)
Java 字节码是相同的,这意味着它与一些较低级别的优化有关。有人可以解释为什么会这样吗?这是基准:
import org.openjdk.jmh.annotations.*;
public class FloatsArrayBenchmark {
public static void main(String[] args) throws Exception {
org.openjdk.jmh.Main.main(new String[]{FloatsArrayBenchmark.class.getSimpleName()});
}
@Benchmark @Fork(value = 1, warmups = 0)
public void times(Data data) {
float[] result = new float[10000];;
for (int i = 0, j=0; i < 9_999; i++,j++)
result[j] = data.floats[i] * 10;
}
@Benchmark …Run Code Online (Sandbox Code Playgroud) 假设您有一个简单的函数,它根据查找表返回一个值,例如:
请参阅有关假设的编辑。
uint32_t
lookup0(uint32_t r) {
static const uint32_t tbl[] = { 0, 1, 2, 3 };
if(r >= (sizeof(tbl) / sizeof(tbl[0]))) {
__builtin_unreachable();
}
/* Can replace with: `return r`. */
return tbl[r];
}
uint32_t
lookup1(uint32_t r) {
static const uint32_t tbl[] = { 0, 0, 1, 1 };
if(r >= (sizeof(tbl) / sizeof(tbl[0]))) {
__builtin_unreachable();
}
/* Can replace with: `return r / 2`. */
return tbl[r];
}
Run Code Online (Sandbox Code Playgroud)
是否有任何超级优化基础设施或算法可以从查找表到优化的 ALU 实现。
动机是我正在为 NUMA 机器构建一些锁,并且希望能够通用地配置我的代码。在 NUMA 锁中,您需要执行 …
考虑以下玩具示例,尤其是result函数:
#include <atomic>
#include <chrono>
#include <iostream>
#include <thread>
class Worker
{
std::thread th;
std::atomic_bool done = false;
int value = 0;
public:
Worker()
: th([&]
{
std::this_thread::sleep_for(std::chrono::seconds(1));
value = 42;
done.store(true, std::memory_order_release);
}) {}
int result() const
{
return done.load(std::memory_order_acquire) ? value : -1;
}
Worker(const Worker &) = delete;
Worker &operator=(const Worker &) = delete;
~Worker()
{
th.join();
}
};
int main()
{
Worker w;
while (true)
{
int r = w.result();
if (r != -1) …Run Code Online (Sandbox Code Playgroud) c++ multithreading atomic micro-optimization memory-barriers