比较c#,c++和Java的性能(c#的奇怪行为)
Comparing c# , c++ and java performance ( Strange behavior of c# )
我正在用C++,C#和Java实现Floyd-Warshall算法。 在每种语言中,我使用顺序和并行实现 测试后结果是:
(运行时间仅适用于主函数和读取文件,变量的Inti和...不测量。
在此处下载源代码
C++
- IDE:Netbeans
- 编译器:MinGW-4.8.1
- 顺序时间 : 9.333000
- 并行时间 : 2.539000
- 将
OpenMp
用于普拉莱尔
如果
NumOfThreads
=1,则为顺序,否则为并行
变量
#define n 1000 /* Then number of nodes */
double dist[n][n];
void floyd_warshall(int NumOfThreads) {
int i, j, k;
omp_set_num_threads(NumOfThreads);
for (k = 0; k < n; ++k)
#pragma omp parallel for private(i,j)
for (i = 0; i < n; ++i)
for (j = 0; j < n; ++j)
if ((dist[i][k] * dist[k][j] != 0) && (i != j))
if ((dist[i][k] + dist[k][j] < dist[i][j]) || (dist[i][j] == 0))
dist[i][j] = dist[i][k] + dist[k][j]; }
.java
- IDE:Netbeans
- 编译器:Netbeans 默认值
- 顺序 : 11.632
- 并行时间 : 3.089
- -Xms512m -Xmx1024m
- import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
爪哇变量
public final int numNodes =1000;
public final double[][] costs= new double[numNodes][numNodes] ;
我没有把Java代码放在这里,因为它工作正常(我认为)
C#
- IDE:Visual Studio 2012
- 编译器:Visual Studio 2012 默认
- 顺序时间 : 31.312
- 并行时间 : 8.920
- 使用System.Threading.Tasks;
变量
const int n = 1000;
static double[,] dist = new double[n, n];
并行代码
static void floyd_warshall(ParallelOptions pOp)
{
int k;
for (k = 0; k < n; ++k)
Parallel.For<int>(0, n, pOp, () => 0, (i, loop, j) =>
{
for (j = 0; j < n; ++j)
if ((dist[i, k] * dist[k, j] != 0) && (i != j))
if ((dist[i, k] + dist[k, j] < dist[i, j]) || (dist[i, j] == 0))
dist[i, j] = dist[i, k] + dist[k, j];
return 0;
}, (j) => { });
单一代码
static void floyd_warshallSingle()
{
int i, j, k;
for (k = 0; k < n; ++k)
for (i = 0; i < n; ++i)
for (j = 0; j < n; ++j)
if ((dist[i,k] * dist[k,j] != 0) && (i != j))
if ((dist[i,k] + dist[k,j] < dist[i,j]) || (dist[i,j] == 0))
dist[i,j] = dist[i,k] + dist[k,j];
}
我的 C# 实现有什么问题?
都使用相同的文件
现在我的问题是为什么用 C# 解决这个算法需要更多时间?Java 和 C++ 的运行时间几乎相同,但我认为我使用 C# 的实现是错误的,因为 C# 和 C++ 之间的这种差异很奇怪!
请帮助我改进我的 C# 实现或说出一些原因谢谢!
编辑 1
我将数组更改为交错数组,结果更改为:
- 顺序 : 19.22
- 并行时间 : 4.903
C#和C ++或Java之间仍然有很大的不同!知道为什么吗?
新变量
const int n = 1000;
static double[][] dist = new double[n][];
新代码 :
static void floyd_warshallSingle()
{
int i, j, k;
for (k = 0; k < n; ++k)
for (i = 0; i < n; ++i)
for (j = 0; j < n; ++j)
if ((dist[i][k] * dist[k][j] != 0) && (i != j))
if ((dist[i][k] + dist[k][j] < dist[i][j]) || (dist[i][j] == 0))
dist[i][j] = dist[i][k] + dist[k][j];
}
static void floyd_warshall(ParallelOptions pOp)
{
int k;
for (k = 0; k < n; ++k)
Parallel.For<int>(0, n, pOp, () => 0, (i, loop, j) =>
{
for (j = 0; j < n; ++j)
if ((dist[i][k] * dist[k][j] != 0) && (i != j))
if ((dist[i][ k] + dist[k][j] < dist[i][ j]) || (dist[i][j] == 0))
dist[i][ j] = dist[i][k] + dist[k][j];
return 0;
}, (j) => { });
}
确定它是否是数组边界检查,或者至少确定数组边界检查是否是问题的一部分的一种方法是删除一些索引计算。例如:
static void floyd_warshallSingle()
{
int i, j, k;
for (k = 0; k < n; ++k)
{
var distk = dist[k];
for (i = 0; i < n; ++i)
{
var disti = dist[i];
for (j = 0; j < n; ++j)
if ((i != j) && (disti[k] * distk[j] != 0))
if ((disti[j] == 0) || disti[k] + distk[j] < disti[j])
disti[j] = disti[k] + distk[j];
}
}
}
在这里,我所做的只是使用 distk
作为dist[k]
的参考。我怀疑编译器已经在进行优化,这可能是您实现从矩形数组到交错数组时获得的性能提升的方式。但值得一试。
另外,您说您在未附加调试器的情况下运行。我假设您也在运行发布版本?所有三个程序(C++,Java和C#)是否运行相同的位数?也就是说,它们都是 64 位可执行文件吗?所有 32 位可执行文件?小心使用 C#,因为可以在项目选项中打开"首选 32 位"标志。这可能会导致您在使用"任何 CPU"进行编译时以 32 位模式运行,即使在 64 位系统上也是如此。
相关文章:
- 删除一个线程上有数百万个字符串的大型哈希映射会影响另一个线程的性能
- OpenMP阵列性能较差
- 递归列出所有目录中的C++与Python与Ruby的性能
- 大小相等但成员数量不同的结构之间的性能差异
- 为什么constexpr的性能比正常表达式差
- 在类中使用随机生成器时出现性能问题
- 在main()之外初始化std::vector会导致性能下降(多线程)
- 海湾合作委员会 ARM 性能下降
- GCC 和 Clang 代码性能的巨大差异
- 在容量内调整矢量大小时的性能影响
- 了解算法的性能差异(如果以不同的编程语言实现)
- 未达到的情况会影响开关外壳性能
- QStringList vs list<shared_ptr<QString>> 性能比较C++
- 是否总是可以将使用递归编写的程序重写为不使用递归的程序C++,性能观点是什么?
- 哪种方法更好,性能明智
- C++ 特征库:引用的性能开销<>
- 与多个 for 循环与单个 for 循环 wrt 相关的性能从多映射获取数据
- 基于范围的 for 循环range_declaration中各种说明符之间的性能差异
- std::p mr::memory_resource 如何与 std::container 产生性能差异?
- 不同的类或结构初始化方法之间的性能差异是什么?