如此处所示, 的行为allocate(0)
未指定。
allocate_at_least(0)
那么,如果我按照C++23标准调用会发生什么呢?行为是实现定义的,还是将被视为allocate(a_non_zero_value)
?
work = pd.DataFrame({"JOB" : ['JOB01', 'JOB01', 'JOB02', 'JOB02', 'JOB03', 'JOB03'],
"STATUS" : ['ON_ORDER', 'ACTIVE','TO_BE_ALLOCATED', 'ON_ORDER', 'ACTIVE','TO_BE_ALLOCATED'],
"PART" : ['PART01', 'PART02','PART03','PART04','PART05','PART06']})
如何使用 Pandas 对作业进行分组,根据值将状态拆分为列,并根据作业连接部分字段。
期望的输出:
JOB | ON_ORDER | ACTIVE | TO_BE_ALLOCATED | PART_CON
JOB01 | True | True | False | Part01\nPart02
JOB02 | True | False | True | Part03\nPart04
JOB03 | False | True | True | Part05\nPart06
此代码在 GCC 和 Clang 中有效,但在 MSVC 上无效:
#include <concepts>
#include <utility>
struct S {};
const S&& f();
S g();
static_assert(std::same_as<decltype(false ? f() : g()), const S>);
https://godbolt.org/z/99rMPzecM
MSVC认为decltype(false ? f() : g())
是const S&&
哪一个是正确的?为什么?
我有一个没有标题行的大型 CSV 文件,并且标题可以作为向量提供给我。我想使用文件列的子集而不加载整个文件。所需列的子集作为单独的列表提供。
编辑:在这种情况下,标题列表中提供的列名称很重要。该 MRE 只有 4 个列名称,但该解决方案应该适用于具有预先指定列名称的大型数据集。问题是列名称仅在外部提供,而不是作为 CSV 文件中的标题。
1,2,3,4
5,6,7,8
9,10,11,12
header <- c("A", "B", "C", "D")
subset <- c("D", "B")
到目前为止,我一直以以下方式读取数据,这得到了我想要的结果,但首先加载整个文件。
# Setup
library(readr)
write.table(
structure(list(V1 = c(1L, 5L, 9L), V2 = c(2L, 6L, 10L), V3 = c(3L, 7L, 11L), V4 = c(4L, 8L, 12L)), class = "data.frame", row.names = c(NA, -3L)),
file="sample-data.csv",
row.names=FALSE,
col.names=FALSE,
sep=","
)
header <- c("A", "B", "C", "D")
subset <- c("D", "B")
# Current approach
df1 <- read_csv(
"sample-data.csv",
col_names = header
)[subset]
df1
# A tibble: 3 × 2
D B
<dbl> <dbl>
1 4 2
2 8 6
3 12 10
如何在不先加载整个文件的情况下获得相同的结果?
相关问题
read.table
(和之间的折衷方案scan
?) [重复]未指定文件外部的列名称,答案不适用于这种情况。我有以下两个问题:(1)我想让标签位于两个刻度之间。我最初的想法是添加辅助刻度并删除主刻度,但是 axis.minor.ticks.length.y 不起作用 (2) 在图例处添加 stat_summary 点 非常感谢您回答您的问题!
这是代码和图:
library("ggplot2")
dt <- data.frame(
ca = rep(c("Oesophageal cancer", "Gastric cancer", "Colorectal cancer"), 3),
var1 = c(1:3, -4:-6, 7:9),
var2 = rep(LETTERS[1:3], 3)
)
dt %>%
ggplot(aes(var1, ca, fill = var2))+
geom_bar(stat="identity", width=0.8)+
stat_summary(fun=sum, geom="point",colour="grey40", fill="grey40", shape=20, size=2)+
geom_vline(xintercept=0, colour="grey30", linetype="dotted")+
theme(
axis.minor.ticks.length.y = rel(0.5)
)
目的:将图1改为图2样式
在 x64 程序集中处理 CALL 的最佳方法是什么,它应该返回到稍微偏移的返回地址?主要涉及效率/执行速度。我将简要解释一下我正在尝试做什么。
背景
我有一种自定义的解释型可视脚本语言,可以编译为本机代码。这种语言具有内置的基于堆栈的协程,以前它们仍然是半解释的(使用单独的堆栈类来存储协程数据)。我正在将其完全本地化,因此仅使用 RSP。
这些协程的一部分是嵌套屈服的能力,这意味着如果协程调用另一个屈服方法,该方法可以在内部屈服以挂起整个调用。该信息通过存储在寄存器中的“YieldState”结构进行处理。这意味着,对于新的完全本地化变体,我们可以使用调用指令从协程中调用生成方法:
call 12345; // [rip+12345] => yieldingMethod
至少在理论上是这样。由于我们的协程是基于堆栈的,因此我们将局部变量简单地存储在堆栈上,而不是像无堆栈协程那样存储在某种类中。这需要通过另一种方法来处理清理(如果协程在完成之前被破坏),我将其称为“中断处理程序”。在我的实际用例中,调用这种中断处理程序很常见,但也不过分。所以我的目标是提供比异常处理程序更快的东西(通常需要对框架进行一些全局查找),但不需要为每个调用显式设置此地址。所以我所做的就是在调用和返回地址之间嵌入中断处理程序地址 - 因为对于旧版本的代码,我们必须手动加载返回,这不是问题:
lea rcx,[rip+25]; // 25 is the assumed byte-size up until the return address
mov rdx,rbx; // load non-native call stack
call prepareMethodYielding; // stores return-address on stack
jmp 12345; // actually call our "yieldingMethod"
mov r15,interruptAddress;
最后一条指令永远不会被执行——我们保留返回地址来实际跳过它。我们在这里只有它能够查找中断处理程序。给定一个恢复地址,我们只需将指针减 8,就得到了恢复中断的地址。在我们的例子中,“mov r15”只是为了让我们能够正确反汇编代码;我们可以单独嵌入地址,但这会使任何外部反汇编程序感到困惑。
实际问题
现在在新版本中,没有“prepareMethodYielding”,而只有一个调用 - 至少是最佳的。但“调用”本身不允许我们修改返回地址,所以这里我面临几个选项,我想知道哪一个是最好的。
选项 A - lea + push + jmp
我们的第一个选择是模拟“调用”,但手动推送返回地址:
lea rax,[rip+10h]
push rax
jmp A6 // yieldingMethod
这需要 3 条指令,但不需要访问内存。
选项 B - 从内存中推送
我们可以通过将返回地址存储在常量内存的某个区域来减少选项的数量:
push qword ptr[rip+1234] // return-address stored here
jmp A6 // yieldingMethod
现在我们只需要一次推送,不需要中间寄存器,尽管现在我们需要访问内存,这可能在数据部分更远。
选项 C - 修改被调用函数中的返回地址
我看到的另一个选择是调整被调用方法内的调用生成的返回地址。这里的所有这些方法都是使用我自己的调用约定编译的,因此它们不遵守 x64 或任何其他。
// caller
call A6 // yielding method
// callee, first instruction
add qword ptr[rsp],10 // size of interrupt-embedding is always the same
这也只是一条指令,具有较小的编码。尽管仅从设计角度来看,我不太喜欢它,因为它将有关被调用者嵌入到调用者中的信息耦合在一起 - 不过,如果这是最有效的变体,我可能仍然会选择它。
选项 D - 根本不修改返回地址
我们的最后一个选择是根本不修改返回地址,而是更改查找和返回的处理方式。
call 12345; // yieldingMethod
mov r15,interruptAddress; // is actually executed now (but value is not used)
因此,在这里,我们将更改查找中断地址的位置(因为返回地址现在指向假指令的前面,而不是后面)。然后,从调用返回后,我们将执行 movabs 指令,但丢弃加载的值。这里的好处是整体代码大小是最小的,因为我们不需要添加任何尚不存在的附加指令。但是,我们正在执行 10 字节 mov 指令,这可能比其他一些变体慢。这在某种程度上取决于 CPU 正在做什么——如果它已经解码了假指令,即使它没有直接到达它,最好的办法就是执行它,而不是修改返回地址。同样的事情,如果 CPU 能够以某种方式检测到指令没有效果,因为它的值永远不会被读取,在寄存器重命名期间,那么它实际上可以是免费的 - atm,我正在使用一个未使用的寄存器,以区分我自己的汇编器;但我想,使用很快就会被覆盖的寄存器可能是有意义的。尽管我不确定这里实际会发生什么。
结论
那么,这 4 个选项中哪一个对您来说最有效?我也对其他想法持开放态度,尽管协程如何完成的总体设计已经完成并且功能齐全,因此像使用 IIRC 某些协程使用的基于状态机的方法之类的方法在这里并不是真正的选择。
我目前正在学习 Rust,我想从拥有字符串的项目向量中收集字符串 (&strs) 的引用。
struct Channel {
cid: usize,
name: String,
}
fn main() {
let channels: Vec<Channel> = vec![Channel {
cid: 1,
name: "Hello".to_string(),
}];
let names: Vec<&str> = channels.iter().map(|x| &x.name).collect();
}
此代码无法编译,出现以下错误:
[E0277]: a value of type `Vec<&str>` cannot be built from an iterator over elements of type `&String`
--> src/main.rs:11:61
|
11 | let names: Vec<&str> = channels.iter().map(|x| &x.name).collect();
| ^^^^^^^ value of type `Vec<&str>` cannot be built from `std::iter::Iterator<Item=&String>`
|
= help: the trait `FromIterator<&String>` is not implemented for `Vec<&str>`
= help: the trait `FromIterator<&str>` is implemented for `Vec<&str>`
= help: for that trait implementation, expected `str`, found `String`
note: the method call chain might not have had the expected associated types
--> src/main.rs:11:44
|
7 | let channels: Vec<Channel> = vec![Channel {
| __________________________________-
8 | | cid: 1,
9 | | name: "Hello".to_string(),
10 | | }];
| |______- this expression has type `Vec<Channel>`
11 | let names: Vec<&str> = channels.iter().map(|x| &x.name).collect();
| ------ ^^^^^^^^^^^^^^^^ `Iterator::Item` changed to `&String` here
| |
| `Iterator::Item` is `&Channel` here
note: required by a bound in `collect`
--> /playground/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/iter/traits/iterator.rs:2050:19
|
2050 | fn collect<B: FromIterator<Self::Item>>(self) -> B
| ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Iterator::collect`
我可以通过调用 as_str() 来提取字符串切片来使其工作:
let names: Vec<&str> = channels.iter().map(|x| x.name.as_str()).collect();
但是,我想了解为什么需要这样做。根据我的理解,由于 deref 强制, a&String
可以转换为 a &str
。为什么我必须明确使用as_str()
?此外,就性能而言,获取as_str()
与引用某个项目相同吗?
我在 g++ 13.2 中得到了奇怪的sizeof()
结果。[[no_unique_address]]
#include <iostream>
using namespace std;
template<bool T>
struct B
{
struct Dummy {};
int *a; // swap position with <below placemark>
// In this position, results are "16" and "40".
[[no_unique_address]] std::conditional_t<T, Dummy, size_t> y;
[[no_unique_address]] std::conditional_t<T, Dummy, size_t> x;
[[no_unique_address]] std::conditional_t<T, Dummy, size_t> h;
[[no_unique_address]] std::conditional_t<T, Dummy, size_t> w;
// <below placemark>
// In this position, results are "8" and "40".
};
int main()
{
cout << sizeof(B<true>) << "\n";
cout << sizeof(B<false>) << "\n";
}
结果是
16
40
但如果你改变int *a;
到线条之后的位置[[no_unique_address]]
,你会得到
8
40
另外,只有一行[[no_unique_address]]
,并且前面有成员指针变量,结果是正确的:
8
16
我阅读了相关文档[[no_unique_address]]
,但没有具体的内容。
为什么会出现这种情况?
atomic_flag_test_and_set
是的!atomic_flag_clear
是的!atomic_flag_test_and_clear
没有atomic_flag_set
没有如果您想在某些上下文中对事件设置标志,并在其他上下文中检查并清除事件,C/C++ 不允许您在每个上下文中执行单个原子调用。
您必须反转标志,因此清除事件上的标志,在检查事件时检查并设置标志。
没什么大不了的,但在这种情况下似乎是倒退的,特别是考虑到标志的默认状态为 false,这在相反的意义上意味着默认情况下会断言事件。
我想,也可以使用原子bool
with来代替。atomic_exchange
以下代码片段在 Java 8 中运行没有错误。但是,当我在 Java 17 中运行相同的代码时,它会失败。
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
public class Main2 {
public static void main(String[] args) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH[:mm[:ss[.SSS]]]X");
OffsetDateTime offSetDateTime = OffsetDateTime.parse("2021-10-09T08:59:00.00Z", formatter);
System.out.println(offSetDateTime);
}
}
在 Java 17 上运行时的输出:
Exception in thread "main" java.time.format.DateTimeParseException: Text '2021-10-09T08:59:00.00Z' could not be parsed at index 19
at java.base/java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:2052)
at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1954)
at java.base/java.time.OffsetDateTime.parse(OffsetDateTime.java:404)
at Main2.main(Main2.java:9)
但是,如果我针对 Java 8 运行相同的代码,则会给出以下结果:
2021-10-09T08:59Z
如果我将测试数据从 更改为"2021-10-09T08:59:00.00Z"
,"2021-10-09T08:59:00.000Z"
它可以在 Java 17 中运行。您知道 Java 17 中的哪些更改导致它失败吗?