几乎每个 OOP 程序员都接触过控制反转的概念。在 C++ 中,我们可以通过动态回调(即 lambda 和函数指针等函子)来实现该原理。但是,如果我们在编译时知道要向驱动程序注入什么过程,理论上我相信有一种方法可以通过组合回调和驱动程序/信号/诸如此类的函数来消除函数传递和调用的开销进入“展开的程序”。这是一个例子。
对于 GUI 程序,我们有关于窗口 1) 设置、2) 循环和 3) 终止的逻辑。我们可以在 1) 窗口设置之后、2) 在每个渲染循环中、3) 和终止之前注入代码。程序方法是这样写:
// Snippet 1:
init_window();
init_input_handler();
init_canvas();
init_socket();
while (!window_should_close()) {
update_window();
handle_input();
draw_on_canvas();
send_through_socket();
}
drop_input_handler();
drop_canvas();
drop_socket();
terminate_window();
Run Code Online (Sandbox Code Playgroud)
OOP 程序员以解耦和适当的抽象为荣。相反,我们这样写:
// Snippet 2:
init_window();
on_window_init_signal.send();
while (!window_should_close()) {
update_window();
on_render_signal.send();
}
on_exit_signal.send();
terminate_window();
Run Code Online (Sandbox Code Playgroud)
但这会带来如上所述的不必要的开销。我的问题是:我们如何利用C++元编程机制来实现零开销控制反转,以便与代码片段2类似形式的代码可以静态地(即在编译时)转换为代码片段1 ?
编辑:我可以想到优化器中广泛存在的循环优化。也许这是该问题的通用版本。
问题很简单:在字符串缓冲区中查找空终止符( '\0' )位置的最快方法是什么?
std::array<char, 100> str { "A sample string literal" };
Run Code Online (Sandbox Code Playgroud)
我想一种选择是使用std::strlen.
我能想到的另一个选择是std::find或者甚至是std::ranges::find:
const auto posOfNull { std::find( str.cbegin( ), str.cend( ), '\0' ) };
Run Code Online (Sandbox Code Playgroud)
ExecutionPolicy现在,如果将(eg std::execution::par) 作为第一个参数传递给它,会有什么不同吗?如果会,那么哪种政策适合这种特殊情况?
或者也许是我不知道的第三个选择?
我正在尝试在 Cython 中循环 2 个 2d 数组。数组具有以下形状:
ranges_1是 的 6000x3 数组int64,而ranges_2是 的 2000x2 数组int64。这个迭代需要执行10000次左右。这意味着嵌套 for 循环内的计算总数约为 2000x6000x10000 = 1200 亿次。
这是我用来生成“虚拟”数据的代码:
import numpy as np
ranges_1 = np.stack([np.random.randint(0, 10_000, 6_000), np.random.randint(0, 10_000, 6_000), np.arange(0, 6_000)], axis=1)
ranges_2 = np.stack([np.random.randint(0, 10_000, 2_000), np.random.randint(0, 10_000, 2_000)], axis=1)
Run Code Online (Sandbox Code Playgroud)
这给出了 2 个像这样的数组:
array([[6131, 1478, 0],
[9317, 7263, 1],
[7938, 6249, 2],
...,
[5153, 426, 5997],
[9164, 9211, 5998],
[1695, 1792, 5999]])
Run Code Online (Sandbox Code Playgroud)
和:
array([[ 433, 558],
[3420, 2494], …Run Code Online (Sandbox Code Playgroud) 我想删除字典中包含特定单词的元素,例如:
my_dict = {
"this is a first example" : 5,
"this is a seconde example" : 3,
"this is a third example" : 2
}
my_list = ["first", "third"]
Run Code Online (Sandbox Code Playgroud)
我想要的结果是这样的:
{'this is a seconde example': 3}
Run Code Online (Sandbox Code Playgroud)
这就是我所做的:
my_new_dict = dict(my_dict)
for sent in my_dict:
for word in sent.split() :
if word in my_list :
del my_new_dict[sent]
break
Run Code Online (Sandbox Code Playgroud)
这个脚本可以工作,但问题是它很长,对于一个大小为 100 万的字典和一个大小为 355K 的单词列表,需要六个多小时。
有没有更好的方法呢?
我最近通读了 CUDA 内核生成的 PTX 代码。我意识到许多寄存器仅用于存储中间值,然后就不再使用,并且 NVCC 通常似乎不太关心寄存器的重用,而是选择在几乎任何新数据点都使用新寄存器被建造。
这就提出了一个问题,是否值得手动检查 PTX 代码并尝试最大限度地减少寄存器的使用,或者 PTX VM 在运行时是否会处理这些事情?
我们可以转发声明一个函数:
void func1();
void func2() {
// use func1
}
void func1() {
// do stuff
}
Run Code Online (Sandbox Code Playgroud)
func1如果调用以下命令,这可能是必要的func2:
void func1();
void func2() {
func1();
}
void func1() {
if (condition) {
func2();
}
}
Run Code Online (Sandbox Code Playgroud)
虽然func1第二个示例中的内联并不困难,但我不知道在任意复杂的程序中是否存在此类编译器优化的理论障碍。在第二种情况下,前向声明是必要的,并且可能会丢失与程序的递归性质相关的编译器优化。
问题:当不需要但仍然使用前向声明时(例如第一个示例),任何主要编译器(gcc、clang、msvc)上是否会丢失任何编译器优化?
c++ optimization recursion forward-declaration compiler-optimization
我目前正在 Python 上使用最小二乘算法,涉及一些大地测量计算。
我选择了Python(它不是最快的)并且它运行得很好。然而,在我的代码中,我有大型稀疏对称(非正定,因此不能使用 Cholesky)矩阵的逆来执行(下图)。我目前使用 np.linalg.inv() ,它使用 LU 分解方法。
我很确定在速度方面需要进行一些优化。
我想到了 Cuthill-McKee 算法来重新排列矩阵并取其逆。您有什么想法或建议吗?
非常感谢您的回答!

作为物理系的学生,我们主要使用 Fortran 进行计算,但我想尝试一些新的东西,发现了 Julia 以及它解决了其他语言的一些问题的事实,我还发现理论上它和 C 一样快,并且想学习它,但是当我尝试将一些代码从 Fortran 移植到 Julia,但发现速度慢得多。作为初学者,我知道可以进行很多优化。所以我想找出并学习良好的实践和优化来应用代码。
is = zeros(64,64)
kp = zeros(Int8, 1,64)
km = zeros(Int8, 1,64)
for i in 1:64
for j in 1:64
is[i,j] = 1
end
end
for i in 1:63
kp[i] = i+1
end
for i in 2:64
km[i] = i-1
end
kp[64]=1
km[1]=64
for T in 1:500
tr::Float32 = T*0.01
for k in 1:1000
for i in 1:64
for j in 1:64
en :: Float64=-1*is[i,j]*(is[kp[i],j]+is[km[i],j]+is[i,kp[j]]+is[i,km[j]])
den:: Float64=-2*en
if (den<0)
is[i,j]=-1*is[i,j]
end …Run Code Online (Sandbox Code Playgroud) 我正在为非常有限的硬件开发一个应用程序,并决定使用 jetpack compose。
当我需要显示卡片列表并且用于它的惰性行变得非常滞后时,问题就出现了。为了进行比较,我选择了一个带有 recyclerView 的示例项目,并用它来显示大致相同的卡片列表,并且滚动尽可能平滑。jetpack compose 本质上比 xml view 慢还是我做错了什么?
撰写代码(我无法准确分享我的代码,但可组合的卡片只是一张带有一些图像、图标和文本的卡片):
@Composable
fun mainComposable(){
...
cardList = remember{ arrayListOf(...) }
lazyList(cardList)
...
}
@Composable
fun lazyList(
cardList: List<CardContent>,
){
LazyRow(
horizontalArrangement = Arrangement.spacedBy(16.dp),
contentPadding = PaddingValues(horizontal = 32.dp)
) {
items(
items = cardList,
key = { it.id }) { item ->
CardComposable(
content = item
)
}
}
}
Run Code Online (Sandbox Code Playgroud)
我已经花了一些时间搜索,所以我发现了很多优化,比如在发布模式下运行,在 build.gradle 上将 minifyEnabled 和收缩资源设置为 true,在 gradle.properties 中将 android.enableR8.fullMode 设置为 true,使用 LazyRow 上的键他们有所帮助,但滚动仍然比带有 recyclerView 的等效 xml 视图应用程序慢。
编辑:添加了 CardComposable …
optimization android lazy-loading android-xml android-jetpack-compose
我正在编写一个用于统计分析和机器学习 (ML) 的 R 包,该包通常非常慢。它很慢,因为它涉及训练和预测模型,包括统计和机器学习。我的包与模型无关,我的意思是它与 R 中的任何其他模型训练和预测包接口,以重新训练他们的模型并使用他们的模型进行预测。经过广泛的分析和代码重构(主要是通过尽可能多地转换为向量化和矩阵运算),我发现无法通过重构进一步加快速度的慢点归结为以下代码:
我想知道Rcpp是否可以帮助加快我的情况。请注意我在这里没有问什么:
我对Rcpp是否有帮助的主要疑问是,最慢的代码是当我调用其他包的 R 函数时。我已经阅读了大量有关 Rcpp 的文章,甚至正在参加有关该主题的 DataCamp 课程。然而,从我目前对 Rcpp 的探索来看,尽管许多资料解释了为什么我们要使用 Rcpp(以加速缓慢的 R 代码),但我无法找到任何资料来清楚地说明 Rcpp 无法帮助解决哪些问题。
据我所知,Rcpp 在调用 R 函数时无法提供任何加速。减慢我的代码速度的函数是由其他包编写的函数。例如,我有一篇文章演示了我的包功能,分别使用nnet::nnet()和nnet::predict.nnet()来训练和预测神经网络,以及分别使用gbm::gbm()和gbm::predict.gbm()来训练和预测梯度增强机。有没有办法使用Rcpp来优化这些函数的调用?
如果我可以Rcpp::cppFunction()实时调用来接收这些函数,将它们编译为 C++,然后继续用我的程序执行它们,那么这可能是一个可行的解决方案。但这对于 Rcpp 来说可能吗?我将不胜感激这里的任何指导。我愿意接受一个明确解释的答案:“不,Rcpp 无法帮助您解决问题,原因如下。”
optimization ×10
c++ ×3
python ×3
algorithm ×1
android ×1
android-xml ×1
c++20 ×1
compile-time ×1
cuda ×1
cython ×1
julia ×1
lazy-loading ×1
matrix ×1
performance ×1
ptx ×1
r ×1
rcpp ×1
recursion ×1
search ×1
string ×1