宜宾 网站建设自己视频怎么上传网站

当前位置: 首页 > news >正文

宜宾 网站建设,自己视频怎么上传网站,网络优化工程师证,o2o电子商务模式的特点引入 当CPU执行程序时#xff0c;需要频繁地访问主存储器#xff08;RAM#xff09;中的数据和指令。然而#xff0c;主存储器的访问速度相对较慢#xff0c;与CPU的运算速度相比存在显著差异#xff0c;每次都从主存中读取数据都会导致相对较长的等待时间#xff0c;从…引入 当CPU执行程序时需要频繁地访问主存储器RAM中的数据和指令。然而主存储器的访问速度相对较慢与CPU的运算速度相比存在显著差异每次都从主存中读取数据都会导致相对较长的等待时间从而降低计算机的整体性能。为了减弱这种速度差异带来的影响计算机系统引入了高速缓存cache作为中间层用于存储主存储器中CPU经常访问的数据和指令。 所以高速缓存应该缓存哪些数据以尽可能提高缓存命中率呢这就涉及到了局部性原理的作用。 局部性原理 局部性原理是指程序访问数据和指令的模式往往具有以下两种特点 时间局部性如果一个存储位置被访问在不久的将来它很可能再次被访问。这意味着计算机系统很可能会重复地访问同一个数据或指令。空间局部性如果一个存储位置被访问附近的存储位置也很可能在不久的将来被访问。这意味着计算机系统在访问数据或指令时很可能会顺序地访问附近的数据或指令。 基于局部性原理高速缓存的设计通常采用了缓存行Cache Line的概念。缓存行是高速缓存中最小的存储单元一般大小为几十字节到几百字节。当CPU访问主存储器的数据时高速缓存将一整个缓存行的数据加载到缓存中而不仅仅是所需的单个数据。这样如果CPU在不久的将来需要附近的数据它们很可能已经在同一缓存行中了从而避免了频繁地访问主存储器。 当我们谈论算法或数据结构的“缓存友好”性质时指的是这些算法或数据结构在计算机的缓存系统中表现良好从而提高程序的性能。缓存友好性是一个重要的性能指标以下是三个缓存友好性的测试例子更深刻体会下缓存友好的重要性。 顺序访问数组 顺序访问数组顺序访问数组中的元素是缓存友好的操作。当程序连续读取数组的元素时计算机缓存可以将整个连续的数据块加载到缓存中从而加快访问速度。相比之下随机访问数组元素可能导致缓存不命中需要频繁地从内存中读取数据降低了访问速度。 通过一个很经典的例子来感受下缓存的存在假设我们有一个二维矩阵并且要对它进行某种操作例如求和或者求积。考虑以下两种遍历方式 行优先遍历按照行优先遍历矩阵先访问第一行的所有元素然后是第二行的所有元素以此类推。列优先遍历按照列优先遍历矩阵先访问第一列的所有元素然后是第二列的所有元素以此类推。 因为局部性原理当我们对矩阵进行遍历时如果采用行优先遍历方式那么连续的内存块都是同一行的元素这样的访问方式在缓存中具有较好的局部性能够更好地利用缓存从而提高访问效率。相比之下如果采用列优先遍历方式由于矩阵中的元素是按列存储的访问过程会在内存中跳跃这会导致缓存不命中降低访问效率。 import java.util.Random;public class CacheFriendlyTest {public static void main(String[] args) {int rows 10000;int cols 10000;int[][] matrix new int[rows][cols];// Fill the matrix with random valuesRandom random new Random();for (int i 0; i rows; i) {for (int j 0; j cols; j) {matrix[i][j] random.nextInt(100);}}// Row-wise traversallong startTime System.currentTimeMillis();long sumRowWise 0;for (int i 0; i rows; i) {for (int j 0; j cols; j) {sumRowWise matrix[i][j];}}long endTime System.currentTimeMillis();System.out.println(Row-wise traversal time: (endTime - startTime) ms);// Column-wise traversalstartTime System.currentTimeMillis();long sumColWise 0;for (int j 0; j cols; j) {for (int i 0; i rows; i) {sumColWise matrix[i][j];}}endTime System.currentTimeMillis();System.out.println(Column-wise traversal time: (endTime - startTime) ms);System.out.println(Sum Row-Wise: sumRowWise);System.out.println(Sum Col-Wise: sumColWise);} }因此虽然两种遍历方式在时间复杂度上是相同的都是 O ( m ∗ n ) O(m * n) O(m∗n)其中 m 和 n 分别是矩阵的行数和列数但行优先遍历的实际表现往往比列优先遍历要好得多。 Row-wise traversal time: 45 ms Column-wise traversal time: 761 ms Sum Row-Wise: 4949822692 Sum Col-Wise: 4949822692紧凑数据结构 使用“紧凑”的数据结构可以提高缓存友好性。例如使用数组而不是链表因为数组的元素在内存中是连续存储的而链表的节点分散在内存中访问链表可能导致缓存不命中。 import java.util.ArrayList; import java.util.Iterator; import java.util.LinkedList;public class CompactDataStructureTest {public static void main(String[] args) {int dataSize 1000000; // 数据规模int repeatCount 1000;// 使用 ArrayList数组实现紧凑的数据结构ArrayListInteger arrayList new ArrayList();for (int i 0; i dataSize; i) {arrayList.add(i);}// 使用 LinkedList链表实现非紧凑的数据结构LinkedListInteger linkedList new LinkedList();for (int i 0; i dataSize; i) {linkedList.add(i);}// 测试 ArrayList 遍历性能long startTime System.currentTimeMillis();for (int i 0; i repeatCount; i) {IteratorInteger arrayIterator arrayList.iterator();while (arrayIterator.hasNext()) {int value arrayIterator.next();// 在这里可以对 value 进行一些操作以避免编译器对循环的优化}}long endTime System.currentTimeMillis();System.out.println(ArrayList traversal time: (endTime - startTime) ms);// 测试 LinkedList 遍历性能startTime System.currentTimeMillis();for (int i 0; i repeatCount; i) {IteratorInteger linkedListIterator linkedList.iterator();while (linkedListIterator.hasNext()) {int value linkedListIterator.next();// 在这里可以对 value 进行一些操作以避免编译器对循环的优化}}endTime System.currentTimeMillis();System.out.println(LinkedList traversal time: (endTime - startTime) ms);} }实际差距并不明显想来 JDK 对 LinkedList 的存储进行了优化。 ArrayList traversal time: 598 ms LinkedList traversal time: 2585 ms矩阵乘法 假设我们有两个 n x n 的矩阵 A 和 B我们想要计算它们的乘积 C。标准的矩阵乘法算法需要 O ( n 3 ) O(n^3) O(n3) 的时间复杂度这是一种较高的复杂度特别是对于大规模的矩阵。 Strassen 算法通过将两个矩阵分解成较小的子矩阵并使用分治策略来减少乘法次数。在理论上Strassen 算法的时间复杂度为 O ( n l o g 2 7 ) O(n^{log_27}) O(nlog2​7)约为 O ( n 2.807 ) O(n^{2.807}) O(n2.807) 但在实际中并不总是比标准的 O(n^3) 算法表现更好原因在于 Strassen 算法涉及多次递归它的计算步骤涉及分解和合并子问题。这种递归的操作可能导致在计算大型矩阵乘法时多次递归调用可能导致较多的缓存不命中从而使得 Strassen 算法的实际性能不如预期。 import org.apache.commons.math3.linear.Array2DRowRealMatrix; import org.apache.commons.math3.linear.RealMatrix;import java.util.Random;public class MatrixMultiplicationTest {public static void main(String[] args) {int n 1000; // 矩阵大小 n x ndouble[][] A new double[n][n];double[][] B new double[n][n];// Fill the matrices with random valuesRandom random new Random();for (int i 0; i n; i) {for (int j 0; j n; j) {A[i][j] random.nextDouble();B[i][j] random.nextDouble();}}// Test Standard Matrix Multiplicationlong startTime System.currentTimeMillis();double[][] C standardMatrixMultiplication(A, B);long endTime System.currentTimeMillis();System.out.println(Standard Matrix Multiplication time: (endTime - startTime) ms);// Test Strassen Matrix MultiplicationstartTime System.currentTimeMillis();double[][] D strassenMatrixMultiplication(A, B);endTime System.currentTimeMillis();System.out.println(Strassen Matrix Multiplication time: (endTime - startTime) ms);}// Standard Matrix Multiplicationpublic static double[][] standardMatrixMultiplication(double[][] A, double[][] B) {int n A.length;double[][] C new double[n][n];for (int i 0; i n; i) {for (int j 0; j n; j) {for (int k 0; k n; k) {C[i][j] A[i][k] * B[k][j];}}}return C;}// Strassen Matrix Multiplicationpublic static double[][] strassenMatrixMultiplication(double[][] A, double[][] B) {// Convert input arrays to RealMatrixRealMatrix matrixA new Array2DRowRealMatrix(A);RealMatrix matrixB new Array2DRowRealMatrix(B);// Perform Strassen matrix multiplicationRealMatrix matrixC matrixA.multiply(matrixB);// Convert the result back to 2D arrayreturn matrixC.getData();} }需要以下依赖 dependencygroupIdorg.apache.commons/groupIdartifactIdcommons-math3/artifactIdversion3.6.1/version !– 版本号可能需要根据您当前使用的版本进行调整 – /dependency测试结果 Standard Matrix Multiplication time: 11608 ms Strassen Matrix Multiplication time: 25238 ms总结 上面几个例子中的代码是非常粗糙不严谨有很多因素没有考虑只是理解下缓存友好的意义希望在实践中有这个意识。