我理解VZEROUPPER在混合SSE和AVX代码时使用很重要,但如果我只使用AVX(和普通的x86-64代码)而不使用任何传统的SSE指令呢?
如果我从不在我的代码中使用单个SSE指令,是否有任何性能原因我需要使用VZEROUPPER?
这假设我没有调用任何外部库(可能使用SSE).
我已经阅读了许多已经回答的与此相关的问题,但没有一个让我清楚地了解当我有多个作者但只有一个读者时应该使用哪个。下面的代码是我正在谈论的一个人为的例子。
struct StateInfo {
long wd{};
uint32_t perc{};
};
class Blah
{
const int numDevices = getDevices();
std::shared_mutex sharedMutexSI_;
vector<StateInfo> stateInfo;
public:
Blah() : stateInfo(numDevices){};
void writers(StateInfo &newSi, const int i)
{
std::shared_lock<std::shared_mutex> _MULTIPLE(sharedMutexSI_);
stateInfo[i] = newSi;
}
StateInfo reader(const int i)
{
std::lock_guard<std::shared_mutex> _EXCLUSIVE(sharedMutexSI_);
return stateInfo[i];
}
};
Run Code Online (Sandbox Code Playgroud)
情况是多个编写者可能同时更新 stateInfo 向量,但永远不会更新向量中的相同项,因为i每个线程都是唯一的。单个读取器线程可以随时尝试读取任何向量项。
上面的代码在避免竞争条件方面是否正确?
是lock_guard正确使用还是我应该使用scoped_lock或unique_lock?
我已经搜索了 stackoverflow 和 google,但无法准确找到我正在寻找的内容,这是:
我有一组 4 字节无符号整数键,最多一百万个左右,我需要将其用作表的索引。最简单的方法是简单地使用键作为数组索引,但当我只使用几百万个条目时,我不想有一个 4GB 的数组!表条目和键是连续的,因此我需要一个保留顺序的哈希函数。
例如
keys = {56, 69, 3493, 49956, 345678, 345679,....etc}
我想把钥匙翻译成{0, 1, 2, 3, 4, 5,....etc}
键可以是任何整数,但总数不会超过 200 万个。由于键(和相应的数组条目)将被删除,因此该数字会有所不同,但新键的编号将始终高于先前编号最高的键。
在上面的示例中,如果密钥 69 被删除,则哈希 3493 返回的哈希整数应该为 1(而不是 2),因为它随后成为第二小的数字。
我希望我能正确解释这一点。以上是否可以通过任何快速有效的哈希解决方案实现?我需要翻译在 100 纳秒以下,但删除我预计需要更长的时间。我查看了 CMPH,但找不到任何不涉及从文件获取数据的使用示例。它需要在linux下运行,并使用纯C语言通过gcc编译。
我希望所有文本和中断都在跨度中,下面的代码就是这样做的。在 IE11 和 chrome 中完美运行,但在 FF 中存在严重问题。也就是说,如果输入的第一个键是<enter>,则光标无法移动到插入的<br>之后。当输入的下一个键位于下一行时,插入符号位置似乎移动,但闪烁的光标没有移动。此外,如果使用退格键删除字符,光标将返回到第一行。
最简单的演示方法:http : //jsfiddle.net/jd2d7n3L/20/
我在 SO 上阅读了许多与此相关的类似问题和答案,但没有一个专门处理这种情况。我怎样才能让 FF 表现得更好?
HTML
<div id=bE contenteditable="true"><br></div>
Run Code Online (Sandbox Code Playgroud)
JS
bE.addEventListener("keypress",KP);
bE.addEventListener("keypress",KU);
function getContainer()
{
var eC=window.getSelection().getRangeAt(0).endContainer;
while(eC&&eC.nodeType==3)eC=eC.parentNode;
return eC
}
function insertElement(E)
{
var sel=window.getSelection(),range=sel.getRangeAt(0);
range.deleteContents();
range.collapse(true);
range.insertNode(E);
range.setStartAfter(E);
range.collapse(true);
sel.removeAllRanges();
sel.addRange(range);
}
function KP(e)
{
var kc=e.which||e.keyCode;
if(e.charCode||e.which===13)
{
var sel=window.getSelection(),range=sel.getRangeAt(0);
var eC=getContainer();
if(eC===bE)
{
eC=document.createElement("span");
range.insertNode(eC);
range.selectNodeContents(eC);
sel.removeAllRanges();
sel.addRange(range);
}
if(kc===13)insertElement(document.createElement("br"));
else insertElement(document.createTextNode(String.fromCharCode(kc)));
e.preventDefault(); …Run Code Online (Sandbox Code Playgroud) 我正在尝试Microsoft.Toolkit.Wpf.UI.Controls.WebView在wpf桌面应用程序中使用控件。它似乎比Web浏览器控件使用的资源少得多,并且基于边缘而更新得多。但是,与webbrowser控件不同,除非选中,否则它将不会滚动。即,当鼠标悬停在Web浏览器上时,无需先选择就可以上下滚动,但是如果Webview不是当前选定的控件,则Webview将忽略鼠标滚轮。
使用VS2019,以下代码演示了该问题。
<Window x:Class="test0.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:WPF="clr-namespace:Microsoft.Toolkit.Wpf.UI.Controls;assembly=Microsoft.Toolkit.Wpf.UI.Controls.WebView"
Title="MainWindow" Height="600" Width="1024">
<Grid>
<StackPanel>
<Button Content="hello world" Height="100" />
<WPF:WebView Source="https://bing.com" Height="250" />
<WebBrowser Source="https://bing.com" Height="250" />
</StackPanel>
</Grid>
</Window>
Run Code Online (Sandbox Code Playgroud)
在运行时,当鼠标指针悬停时,两个浏览器控件都将滚动。单击按钮(从两个浏览器中移出焦点)后,只有Web浏览器控件在鼠标悬停时滚动。
是否有解决此问题的解决方法?
使用:.NET Framework 4.7.2和Microsoft.Toolkit.Wpf.UI.Controls.WebView 5.1.1
我正在虚拟机中编写自定义操作系统,并且无法从IOAPIC mmio寄存器中成功编写和读取.即它似乎忽略了索引寄存器写入.加载后R8与IOAPIC基地址(从ACPI枚举确定为0xFEC00000),我使用下面的程序来读/写:
; -----------------------------------------------------------------------------
; IN : RAX = ioapic address, EBX = index register
; OUT: ECX = return value
ioapic_read:
mov [r8], ebx
mov ecx, [r8 + 0x10]
ret
; -----------------------------------------------------------------------------
; IN : RAX = ioapic address, EBX = index register, ECX = value
; OUT: -
ioapic_write:
mov [r8], ebx
mov [r8 + 0x10], ecx
ret
Run Code Online (Sandbox Code Playgroud)
但是ioapic_read将始终返回写入的最后一个值(通过ioapic_write),而不管使用的索引如何.我有身份分页设置使用0x9B我认为应该禁用缓存.
我试过pause在每个movs 之后使用.没有帮助.在mfences之间试过mov.没有帮助.
我已确认0xFEC00000地址已成功标识映射.
看起来还有一些缓存正在进行中.我错过了什么?
编辑
我发现这不是一个缓存问题,而是一些很奇怪的东西 - …
从Windows 8开始,WS_EX_LAYERED可以在子控件上使用,(因此称MSDN)。但是我一直无法使其工作。在下面的代码中,我试图使子控件成为半透明的,但是在控件上使用WS_EX_LAYERED时,没有任何效果。
int APIENTRY wWinMain(_In_ HINSTANCE hInst, _In_opt_ HINSTANCE hPrevInst, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow)
{
WNDCLASSEX wc = {};
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WndProc;
wc.hInstance = hInst;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.lpszClassName = _T("main");
wc.hCursor = LoadCursor(0, IDC_ARROW);
RegisterClassEx(&wc);
HWND MWhwnd = CreateWindowEx(NULL, _T("main"), _T(""),
WS_OVERLAPPEDWINDOW| WS_CLIPCHILDREN,
CW_USEDEFAULT, 0, CW_USEDEFAULT,0, NULL, NULL, hInst, NULL);
wc.lpfnWndProc = WndProcPanel;
wc.lpszClassName = _T("CPanel");
wc.style = NULL;
RegisterClassEx(&wc);
HWND Panelhwnd = CreateWindowEx(WS_EX_LAYERED, _T("CPanel"), _T(""),
WS_VISIBLE …Run Code Online (Sandbox Code Playgroud) 我知道之前已经回答了类似的问题但是我已经搜索了stackoverflow(等)并且没有找到关于如何处理实例化并在程序中仅使用一次的小类的明确想法.在单独的文件中保留声明和实现是否真的很重要?
请看以下示例:
// timer.hpp
#pragma once
#include "presets.h" // includes #defines for u64 -> uint64_t, etc
class Timer {
public:
Timer() {}
Timer(u64 elt) : elt_(elt) {}
void startTiming() { if (NOT running_){ running_ = true; sTime_ = GetTickCount64(); }};
void stopTiming() { if (running_) { running_ = false; eTime_ = GetTickCount64(); elt_ += (eTime_ - sTime_); sTime_ = eTime_; }}
u64 getElapsed() { if (NOT running_) return elt_; eTime_ = GetTickCount64(); return elt_ + eTime_ - sTime_; }
private: …Run Code Online (Sandbox Code Playgroud) 我有一个归零的128位寄存器,我想向左移位并添加一个字节.我可以改为:
pslldq xmm0, 1
Run Code Online (Sandbox Code Playgroud)
......但是现在我想将al复制到空白区域.就像是:
or xmm0, al
Run Code Online (Sandbox Code Playgroud)
这当然不起作用.我只希望受影响的最低8位.这将是一个循环,其中al的连续值将用于填充寄存器.所以我需要一些mov指令或其他替代方案.
理想的是单个指令向左移8位并插入,但我不认为存在这样的指令.
我花了很多时间在x86-64指令集数据中翻找,但找不到任何可以让我做我想做的事情.可以吗?
更新:尝试使用pinsrb后,我在代码逻辑中发现了一个错误.pinsrb会很棒但不幸的是它只能使用立即索引而不是寄存器.
我从非连续位置获取字节,所以我认为我需要一次一个字节.字节数可以是1到16之间的任何字节.我抓取的第一个字节应该以xmm0的最低字节结束,下一个字节进入下一个最低字节等.
我想要实现的是基于一个字节中的每个位,设置为ymm寄存器(或内存位置)中每个dword中的所有位
例如
al = 0110 0001
ymm0 = 0x00000000 FFFFFFFF FFFFFFFF 00000000 00000000 00000000 00000000 FFFFFFFF
Run Code Online (Sandbox Code Playgroud)
即vmovmskps eax, ymm0/ 的倒数_mm256_movemask_ps,将位图转换为矢量蒙版.
我想有一些sse/avx指令可以相对简单地做到这一点,但我还是无法解决这个问题.优选沙桥兼容,因此没有avx2.