有没有办法删除数组边界检查C#?
这是我想要实现的目标:
public static int F(int[] M, int i)
{
return M[i]; // I can guarantee that [i] will never be outside of [0, M.Length]
}
Run Code Online (Sandbox Code Playgroud)
在这个函数调用之前,我有一个逻辑已经检查了边界(其中有一些额外的逻辑)。我要删除的内容如下:
Program.F(Int32[], Int32)
L0000: sub rsp, 0x28
L0004: cmp edx, [rcx+8] ; I don't need this line
L0007: jae short L0015 ; I don't need this line
L0009: movsxd rax, edx
L000c: mov eax, [rcx+rax*4+0x10]
L0010: add rsp, 0x28
L0014: ret
L0015: call 0x00007ffc8877bc70 ; I don't need this line
L001a: int3 …Run Code Online (Sandbox Code Playgroud) 我有以下代码,它将数据从内存复制到DMA缓冲区:
for (; likely(l > 0); l-=128)
{
__m256i m0 = _mm256_load_si256( (__m256i*) (src) );
__m256i m1 = _mm256_load_si256( (__m256i*) (src+32) );
__m256i m2 = _mm256_load_si256( (__m256i*) (src+64) );
__m256i m3 = _mm256_load_si256( (__m256i*) (src+96) );
_mm256_stream_si256( (__m256i *) (dst), m0 );
_mm256_stream_si256( (__m256i *) (dst+32), m1 );
_mm256_stream_si256( (__m256i *) (dst+64), m2 );
_mm256_stream_si256( (__m256i *) (dst+96), m3 );
src += 128;
dst += 128;
}
Run Code Online (Sandbox Code Playgroud)
这就是gcc程序集输出的样子:
405280: c5 fd 6f 50 20 vmovdqa 0x20(%rax),%ymm2
405285: c5 …Run Code Online (Sandbox Code Playgroud) 因此,对于我在计算机系统课程中的最终作业,我们需要优化这些forloops,使其比原始版本更快.使用我们的linux服务器,基本等级不到7秒,完整等级不到5秒.我在这里的代码大约需要5.6秒.我想我可能需要以某种方式使用指针来使它更快,但我不是很确定.任何人都可以提供我的任何提示或选项吗?非常感谢!
QUICKEDIT:文件必须保持50行或更少,我忽略了教师所包含的那些注释行.
#include <stdio.h>
#include <stdlib.h>
// You are only allowed to make changes to this code as specified by the comments in it.
// The code you submit must have these two values.
#define N_TIMES 600000
#define ARRAY_SIZE 10000
int main(void)
{
double *array = calloc(ARRAY_SIZE, sizeof(double));
double sum = 0;
int i;
// You can add variables between this comment ...
register double sum1 = 0, sum2 = 0, sum3 = 0, sum4 = 0, sum5 = 0, …Run Code Online (Sandbox Code Playgroud) 我手动矢量化循环并一次处理4个项目.项目总数可能不是4的倍数,所以我在主循环结束时留下了一些项目.我认为如果计数大于4并且重做某些项目是安全的,我可以使用相同的主矢量化循环执行剩余项目.例如,如果我需要处理10个项目,我可以在三次迭代中处理0123,4567,6789.我找不到任何对这种技术的引用.它是愚蠢但我不明白怎么样?
#include <stdint.h>
#include <stddef.h>
void inc(int32_t const* __restrict in, int32_t* out, size_t count)
{
if (count < 4)
{
for (size_t i = 0; i < count; ++i)
out[i] = in[i] + 42;
}
else
{
typedef int32_t v4i __attribute__ ((vector_size (16), aligned(4)));
for (size_t i = 0;;)
{
for (; i + 4 <= count; i += 4)
{
(v4i&)out[i] = (v4i&)in[i] + 42;
}
if (i == count)
break;
i = count - 4;
}
}
}
Run Code Online (Sandbox Code Playgroud) 我希望能够手动预测任意算术的长度(即没有分支或内存,尽管这也很好)x86-64汇编代码将采用特定的体系结构,考虑到指令重新排序,超标量,延迟,消费者价格指数等
什么/描述必须遵循的规则才能实现这一目标?
我想我已经找到了一些初步规则,但是我没有找到任何关于将任何示例代码分解为这个详细程度的引用,所以我不得不做一些猜测.(例如,英特尔优化手册甚至几乎没有提到指令重新排序.)
至少,我正在寻找(1)确认每条规则是正确的,或者是每条规则的正确陈述,以及(2)我可能忘记的任何规则的列表.
addps并且subps使用相同的功能) unit?我如何确定?).和:4此循环已经发出少于超标量宽度(通常)指令的数量.例如,请考虑以下示例代码(计算交叉产品):
shufps xmm3, xmm2, 210
shufps xmm0, xmm1, 201
shufps xmm2, xmm2, 201
mulps xmm0, xmm3
shufps xmm1, xmm1, 210
mulps xmm1, xmm2
subps xmm0, xmm1
Run Code Online (Sandbox Code Playgroud)
我试图预测Haswell的延迟看起来像这样:
; `mulps` Haswell latency=5, CPI=0.5
; `shufps` Haswell latency=1, CPI=1
; `subps` Haswell latency=3, CPI=1
shufps xmm3, xmm2, 210 ; cycle 1
shufps xmm0, xmm1, 201 ; cycle 2
shufps xmm2, xmm2, 201 ; …Run Code Online (Sandbox Code Playgroud) 我有 2 个相邻的大小相同的字节缓冲区(每个缓冲区大约 20 MB)。我只是想数一下它们之间的差异。
该循环在具有 3600MT RAM 的 4.8GHz Intel I7 9700K 上运行需要多长时间?
我们如何计算最大理论速度?
uint64_t compareFunction(const char *const __restrict buffer, const uint64_t commonSize)
{
uint64_t diffFound = 0;
for(uint64_t byte = 0; byte < commonSize; ++byte)
diffFound += static_cast<uint64_t>(buffer[byte] != buffer[byte + commonSize]);
return diffFound;
}
Run Code Online (Sandbox Code Playgroud)
在我的电脑(9700K 4.8Ghz RAM 3600 Windows 10 Clang 14.0.6 -O3 MinGW)上需要 11 毫秒,我觉得它太慢了,而且我错过了一些东西。
CPU 读取 40MB 的时间应该少于 2 毫秒(我的 RAM 带宽在 20 到 30GB/s 之间)
我不知道如何计算执行一次迭代所需的周期(特别是因为现在的 CPU 是超标量)。如果我假设每个操作有 …
使用英特尔编译器内在函数,给定一个128位寄存器,打包8个16位元素,如何从寄存器中访问(廉价)任意元素,以便后续使用_mm_cvtepi8_epi64(符号扩展两个8位元素,打包在较低位置) 16位寄存器,两个64位元素)?
我会解释为什么我问:
0x0和包装两个四字(64位)0xffff ffff ffff ffff.注意:输入缓冲区的值0x0和值0xff可以更改为最有用的值,前提是在总和之前屏蔽效果仍然存在.
从我的问题可以明显看出,我目前的计划如下,在输入缓冲区中流式传输:
谢谢,阿萨夫
我正在编写一个程序来检测素数.其中一部分是筛选可能的候选人.我写了一个相当快的程序,但我想我会看到是否有人有更好的想法.我的程序可以使用一些快速收集和分散指令,但我只限于AVX2硬件用于x86架构(我知道AVX-512有这些但我不确定它们有多快).
#include <stdint.h>
#include <immintrin.h>
#define USE_AVX2
// Sieve the bits in array sieveX for later use
void sieveFactors(uint64_t *sieveX)
{
const uint64_t totalX = 5000000;
#ifdef USE_AVX2
uint64_t indx[4], bits[4];
const __m256i sieveX2 = _mm256_set1_epi64x((uint64_t)(sieveX));
const __m256i total = _mm256_set1_epi64x(totalX - 1);
const __m256i mask = _mm256_set1_epi64x(0x3f);
// Just filling with some typical values (not really constant)
__m256i ans = _mm256_set_epi64x(58, 52, 154, 1);
__m256i ans2 = _mm256_set_epi64x(142, 70, 136, 100);
__m256i sum = _mm256_set_epi64x(201, 213, 219, 237); // …Run Code Online (Sandbox Code Playgroud) 这些加载指令之间的性能有差异吗mov?与简单的寻址模式相比,更复杂的寻址模式是否有额外的开销(延迟或吞吐量)?
# AT&T syntax # Intel syntax:
movq (%rsi), %rax mov rax, [rsi]
movq (%rdi, %rsi), %rax mov rax, [rdi + rsi]
movq (%rdi, %rsi, 4), %rax mov rax, [rdi + rsi*4]
Run Code Online (Sandbox Code Playgroud) 我正在修改AVX-2指令,我正在寻找一种快速计算__m256i单词中前导零数(具有256位)的方法.
到目前为止,我已经找到了以下方法:
// Computes the number of leading zero bits.
// Here, avx_word is of type _m256i.
if (!_mm256_testz_si256(avx_word, avx_word)) {
uint64_t word = _mm256_extract_epi64(avx_word, 0);
if (word > 0)
return (__builtin_clzll(word));
word = _mm256_extract_epi64(avx_word, 1);
if (word > 0)
return (__builtin_clzll(word) + 64);
word = _mm256_extract_epi64(avx_word, 2);
if (word > 0)
return (__builtin_clzll(word) + 128);
word = _mm256_extract_epi64(avx_word, 3);
return (__builtin_clzll(word) + 192);
} else
return 256; // word is entirely zero
Run Code Online (Sandbox Code Playgroud)
但是,我发现在256位寄存器中找出确切的非零字是相当笨拙的.
有人知道是否有更优雅(或更快)的方法吗?
正如附加信息:我实际上想要计算由逻辑AND创建的任意长向量的第一个设置位的索引,并且我将标准64位操作的性能与SSE和AVX-2代码进行比较.这是我的整个测试代码:
#include <stdio.h> …Run Code Online (Sandbox Code Playgroud) assembly ×7
performance ×5
c ×4
optimization ×4
simd ×4
x86 ×4
intrinsics ×2
x86-64 ×2
algorithm ×1
arrays ×1
avx ×1
avx2 ×1
c# ×1
clang++ ×1
debug-mode ×1
gcc ×1
latency ×1
loops ×1
pipeline ×1
sse ×1
superscalar ×1