在今天的编程中你看到的最糟糕的(由于流行程度或严重程度)抽象反转的例子是什么?
对于那些不熟悉这个概念的人来说,抽象反转是在高级构造之上实现低级构造.更确切地说,假设你有构造A和B.B是在A之上实现的,但A不会在任何地方暴露.因此,如果你真的需要较低级别的构造A,那么当B首先用A实现时,你最终会在B之上实现A. 见http://en.wikipedia.org/wiki/Abstraction_inversion.
背景: 我正在尝试创建一个纯D语言实现的功能,大致相当于C的memchr,但使用数组和索引而不是指针.原因是std.string将用于编译时功能评估.对于那些不熟悉w/D的人,如果满足某些限制,可以在编译时评估函数.一个限制是它们不能使用指针.另一个是他们不能调用C函数或使用内联汇编语言.使字符串库在编译时工作对于某些编译时代码生成很有用.
问题: memchr如何在引擎盖下工作以尽可能快地执行?在Win32上,我使用简单循环在纯D中创建的任何东西,即使有明显的优化技术,例如禁用边界检查,循环展开等,也至少要慢2倍.有哪些非显而易见的技巧可用于像在字符串中查找字符一样简单?
比方说,我有三个阵列a,b和c等长的N.每个数组的元素都来自一个完全有序的集合,但没有排序.我还有两个索引变量,i和j.对于所有人i != j,我想计算索引对的数量a[i] < a[j],b[i] > b[j]以及c[i] < c[j].有没有办法可以在低于O(N ^ 2)的时间复杂度下完成,例如通过创造性地使用排序算法?
注意:这个问题的灵感来源于,如果你只有两个数组,a并且b你可以找到索引对的数量,a[i] < a[j]并且b[i] > b[j] 在O(N log N)中使用合并排序.我基本上正在寻找三个数组的推广.
为简单起见,您可以假设任何数组中没有两个元素相等(无关系).
在什么情况下,让两个不同的线程同时写入x86上相同阵列的相邻元素是不安全的?据我所知,在一些类似DS9K的体系结构中使用疯狂的内存模型会导致单词撕裂,但在x86单字节上是可寻址的.例如,在D编程语言real中,x86上是80位浮点类型.做以下事情是否安全:
real[] nums = new real[4]; // Assume new returns a 16-byte aligned block.
foreach(i; 0..4) {
// Create a new thread and have it do stuff and
// write results to index i of nums.
}
Run Code Online (Sandbox Code Playgroud)
注意:我知道,即使这是安全的,它有时也会导致缓存的错误共享问题,从而导致性能降低.但是,对于我想到的用例,写入的内容很少,实际上并不重要.
编辑:不要担心读回写入的值.假设在读取任何值之前将存在同步.我只关心这种写作的安全性.
parallel-processing multithreading d thread-safety race-condition
我正在尝试用D编程语言编写一个函数来替换对C的strtold的调用.(基本原理:要使用来自D的strtold,你必须将D字符串转换为C字符串,这是低效的.另外,strtold不能在编译时执行.)我想出了一个主要有效的实现,但是我似乎在最不重要的位上失去了一些精确度.
算法的有趣部分的代码如下,我可以看到精度损失来自哪里,但我不知道如何摆脱它.(我遗漏了许多与核心算法无关的代码部分,以节省人们的阅读.)什么字符串到浮点算法将保证结果尽可能接近IEEE编号line到字符串表示的值.
real currentPlace = 10.0L ^^ (pointPos - ePos + 1 + expon);
real ans = 0;
for(int index = ePos - 1; index > -1; index--) {
if(str[index] == '.') {
continue;
}
if(str[index] < '0' || str[index] > '9') {
err();
}
auto digit = cast(int) str[index] - cast(int) '0';
ans += digit * currentPlace;
currentPlace *= 10;
}
return ans * sign;
Run Code Online (Sandbox Code Playgroud)
此外,我正在使用旧版本的单元测试,其中包括:
assert(to!(real)("0.456") == 0.456L);
Run Code Online (Sandbox Code Playgroud)
我的函数生成的答案是否有可能比解析浮点文字时编译器生成的表示更准确,但编译器(用C++编写)总是与strtold完全一致,因为它在内部使用strtold进行解析浮点文字?
有没有我可以用OMF对象格式获得Windows的预编译BLAS和LAPACK二进制文件?我想将一些D语言代码链接到这些.我知道在哪里可以获得COFF格式的相关库.我也知道objconv工具,它将COFF转换为OMF,尽管由于我不完全理解的原因,这似乎在实践中不起作用.这些似乎与符号中的下划线有关,尽管我尝试了几乎每个设置来处理这些并且似乎都没有.
或者,是否有人知道如何将引用二进制文件转换为OMF,以便它们实际上可以正确链接到DMD编译的代码?作为最后的手段,有谁知道如何使用DMC构建CLAPACK,CBLAS和F2CLIB?这些附带的构建过程似乎完全面向GCC工具链.
我写了科学研究代码,特别是生物信息学.当然,在科学中,结果应该是可重复的.那些没有定期参与项目并且不详细了解基础设施的人可能合法地希望看到我的代码来重现结果.问题在于,使代码自足以容易地给这样的人提供/解释似乎严重限制了可能的重用量.
将几个相关项目中使用的功能分解为个人库通常很方便,但是将这些库转储5000行(不可否认的文档很少,因为它不是生产/发布质量)代码没有任何帮助是不方便的.处理那些想要快速重现结果的人手头的问题.
在您的系统上安装一组几个密钥库并且可以随时使用而不必考虑两次通常很方便,但向主要是科学家的人解释并不方便,而不是程序员如何设置所有这些东西.如果您自己不记得某些细节,尤其如此.(注意,虽然有问题的细节是与科学无关的技术细节.)
将研究项目的几个相关方面的所有代码保存在一个大型程序中通常很方便,而不是为您尝试的每个轻微变化/事物编写完全自包含的代码,但同样,转储所有代码并不方便这个,或解释所有这些,只是想要重现结果的人.
有哪些方法可以解决这些问题,以便我可以重用代码,但是仍然允许想要重现我的结果的人以合理的努力来启动和运行代码?请注意,我的问题的核心是创建可重用的代码库的可能性,这些代码库不是很成熟.
maintenance readability scientific-computing self-contained libraries
我正在尝试使用D编程语言的MPI.D完全支持C ABI,可以链接并调用任何C代码.我已经完成了显而易见的事情并将MPI标题翻译为D.然后我将测试程序从维基百科翻译成D.我使用以下命令编译它:
dmd test.d -L-lmpistubs
它在我刚运行时起作用./test,并打印:
0: We have 1 processors
但是,当我跑步时mpiexec -n 8 test,它什么都不打印.我的理解是MPI可执行文件需要一堆奇怪的链接选项,这就是mpicc存在自动化过程的工具的原因.但是,如果我在D中尝试使用MPI,这对我没有帮助.我认为这是因为我没有使用正确的链接器选项.有人可以告诉我mpicc,我可以做什么以及如何让DMD做同样的事情?
编辑:我找到了答案mpicc -showme.这显示了mpicc转发的命令gcc.但是,我也意识到我做错了头文件翻译.下一个问题: 如何做对.
我理解动态链接的好处(旧代码可以自动利用库升级,它更节省空间),但它肯定有缺点,特别是在异构Linux生态系统中.由于系统升级破坏了向后兼容性或将回归引入共享库,因此很难分发"正常工作"的分布式无关二进制文件并使之前工作的程序更容易中断.
鉴于这些缺点,为什么动态链接似乎是如此普遍受欢迎?为什么要找到静态链接的,与发行版无关的Linux二进制文件,即使对于小型应用程序也是如此困难?
linux linker shared-libraries dynamic-linking static-linking
我正在尝试优化一些应该从内存中读取单精度浮点数的代码,并以双精度对它们进行算术运算.这正成为一个重要的性能瓶颈,因为将数据作为单一精度存储在内存中的代码比将内存中的数据存储为双精度的等效代码要慢得多.下面是一个玩具C++程序,它捕获了我的问题的本质:
#include <cstdio>
// noinline to force main() to actually read the value from memory.
__attributes__ ((noinline)) float* GetFloat() {
float* f = new float;
*f = 3.14;
return f;
}
int main() {
float* f = GetFloat();
double d = *f;
printf("%f\n", d); // Use the value so it isn't optimized out of existence.
}
Run Code Online (Sandbox Code Playgroud)
GCC和Clang都执行加载*f和转换为双精度作为两个单独的指令,即使cvtss2sd指令支持内存作为源参数.根据Agner Fog的说法,cvtss2sd r, m执行速度和movss r, m大多数架构一样快,并且无需执行cvtss2sd r, r后续操作.尽管如此,Clang生成以下代码main(): …
d ×5
performance ×3
linker ×2
abstraction ×1
algorithm ×1
assembly ×1
blas ×1
c ×1
lapack ×1
libraries ×1
linux ×1
maintenance ×1
math ×1
mpi ×1
mpiexec ×1
object-files ×1
omf ×1
readability ×1
sorting ×1
sse ×1
statistics ×1
theory ×1
x86-64 ×1