两个大文件彼此的平行余弦相似度

2024-02-20

我有两个文件:A 和 B

A has 400,000 lines each having 50 float values
B has 40,000 lines having 50 float values.

对于 B 中的每一行,我需要在 A 中找到相似度 >90%(余弦)的对应行。

对于线性搜索和计算,代码需要大量的计算时间。 (40-50小时)

向社区寻求有关如何加快流程的建议(用于实现该流程的博客/资源(例如 AWS/云)的链接)。已经被这个问题困扰了一段时间了!

[有人提到 rpud/rpudplus 可以做到这一点,但似乎无法在云资源上执行它们]

注意:根据要求,余弦相似度的代码为:

for line1, line2 in zip(f1, f2):
    line1 = line1[:-1]
    cnt = cnt + 1
    l2X = [float(i) for i in line2.split()]
    f3 = open(enLabelValues, 'r')
    f4 = open(enVectorValues, 'r')
    print cnt
    cnt_j = 0
    for line3, line4 in zip(f3, f4):
        line3 = line3[:-1]
        l4X = [float(i) for i in line4.split()]
        ########This is the line for spatial cosine similarity
        result = 1 - spatial.distance.cosine(l2X, l4X)
        cnt_j = cnt_j + 1
        if(result > float(0.95)):
            if line3 not in a.keys():
                a[line3] = True
                fLabel_2.write(line3+"\n")
                fX_2.write(line4)
        fLabel_2.flush()
        fX_2.flush()
        os.fsync(fLabel_2.fileno())
        os.fsync(fX_2.fileno())

我可以生成 40,000 行和 400,000 行的合成文件,每行 50 个样本,并在合理的 4 核(+超线程)桌面 iMac 上以我笨拙的 C++ 风格在大约 2 分 18 秒内处理它们,无需任何 SIMD 优化(由我)使用GNU 并行.

这是顶级脚本。您可以看到它生成了测试数据"a.txt" and "b.txt"。然后它“压缩” "b.txt"到相同的二进制表示,并将预先计算的幅度附加到每行。最后,它对行进行编号"a.txt"并将它们传递到GNU 并行它将这些行分成大约 5,200 行的组,并启动一组 8 个并行进程,将其中的每行与 B 中的 40,000 行进行比较。

#!/bin/bash

# Generate test data - a.txt b.txt
./generate

# Preprocess b.txt into binary with precomputed magitudes save as B
./preprocess

# Process file A in batches
cat -n a.txt | parallel --block-size 2M --line-buffer --pipe ./process {#}

这是用于综合数据的generate.cpp程序:

#include <iostream>
#include <cstdlib>
#include <fstream>
#include "common.h"

using namespace std;

int main()
{
   int line,sample;
   ofstream a("a.txt");
   if (!a.is_open()){
      cerr << "ERROR: Unable to open output file";
      exit(EXIT_FAILURE);
   }
   for(line=0;line<ALINES;line++){
      for(sample=0;sample<SAMPLESPERLINE;sample++){
         a << (float)rand()*100/RAND_MAX << " ";
      }
      a << endl;
   }
   a.close();
   ofstream b("b.txt");
   if (!b.is_open()){
      cerr << "ERROR: Unable to open output file";
      exit(EXIT_FAILURE);
   }
   for(line=0;line<BLINES;line++){
      for(sample=0;sample<SAMPLESPERLINE;sample++){
         b << (float)rand()*100/RAND_MAX << " ";
      }
      b << endl;
   }
   b.close();
}

这是preprocess.cpp代码:

#include <sstream>
#include <fstream>
#include <string>
#include <iostream>
#include <stdlib.h>
#include <vector>
#include <cmath>
#include "common.h"

int main(int argc, char* argv[]){

   std::ifstream btxt("b.txt");
   std::ofstream bbin("B",std::ios::out|std::ios::binary);
   if (!btxt.is_open()){
      std::cerr << "ERROR: Unable to open input file";
      exit(EXIT_FAILURE);
   }
   if (!bbin.is_open()){
      std::cerr << "ERROR: Unable to open output file";
      exit(EXIT_FAILURE);
   }

   int l=0;
   std::string line;
   std::vector<float> v;
   v.resize(SAMPLESPERLINE+1);
   while (std::getline(btxt,line)){
      std::istringstream iss(line);
      v.clear();
      float f;
      double magnitude;
      magnitude=0.0;
      int s=0;
      while (iss >> f){
         v[s]=(f);
         magnitude+=(double)f*f;
         s++;
      }
      // Append the magnitude to the end of the "line"
      v[s]=(float)sqrt(magnitude);
      // Write the samples and magnitide in binary to the output file
      bbin.write(reinterpret_cast<char*>(&v[0]),(SAMPLESPERLINE+1)*sizeof(float));
      l++;
   }
   btxt.close();
   bbin.close();

   return EXIT_SUCCESS;
}

这里是common.h file:

const int ALINES=400000;
const int BLINES=40000;
const int SAMPLESPERLINE=50;

这是process.cpp code:

#include <sstream>
#include <fstream>
#include <string>
#include <iostream>
#include <stdlib.h>
#include <vector>
#include <array>
#include <cmath>
#include "common.h"

int main(int argc, char* argv[]){

   if(argc!=2){
      std::cerr << "Usage: process JOBNUM" << std::endl;
      exit(1);
   }
   int JobNum=std::atoi(argv[1]);
   std::cerr << "Starting job: " << JobNum << std::endl;

   // Load B
   std::ifstream bbin("B",std::ios::binary);
   if (!bbin.is_open()){
      std::cerr << "ERROR: Unable to open B";
      exit(EXIT_FAILURE);
   }

   int l=0;
   std::array<float,SAMPLESPERLINE+1> record;
   std::vector<std::array<float,SAMPLESPERLINE+1>> B;
   B.resize(BLINES);
   for(l=0;l<BLINES;l++){
      // Read one record of 50 floats and their magnitude
      bbin.read(reinterpret_cast<char*>(&B[l][0]),sizeof(float)*(SAMPLESPERLINE+1));
   }
   bbin.close();

   // Process all lines read from stdin, each line prepended by its line number
   // Format is:
   // <line number in file "a.txt"> <SAMPLE0> <SAMPLE1> ... <SAMPLE49>
   int nLines=0;
   std::string line;
   while (std::getline(std::cin,line)){
      nLines++;
      std::istringstream iss(line);
      std::vector<float> A;
      A.resize(SAMPLESPERLINE);
      float f;
      int Alineno;
      int s=0;
      iss >> Alineno;
      double dMag=0.0;
      while (iss >> f){
         A[s++]=f;
         dMag+=(double)f*f;
      }
      // Root magnitude
      float AMagnitude=(float)sqrt(dMag);

      // At this point we have in B, 40,000 records each of 50 samples followed by the magnitude
      // ... and we have a single record from "a.txt" with 50 samples and its magnitude in AMagnitude
      // ... and Alineno is the absolute line number in "a.txt" of this line
      // Time to do the actual calculation: compare this record to all records in B
      for(int brec=0;brec<BLINES;brec++){
         float BMagnitude=B[brec][SAMPLESPERLINE];
         double dotproduct=0.0;
         float *a = &A[0];
         float *b = &B[brec][0];
         for(s=0;s<SAMPLESPERLINE;s++){
            dotproduct += (*a++) * (*b++);
         }
         float similarity = dotproduct/(AMagnitude*BMagnitude);
         if(similarity>0.99){
            std::cout << "Line A: " << Alineno << ", line B: " << brec << ", similarity:" << similarity << std::endl;
         }
      }
   }
   std::cerr << "Ending job: " << JobNum << ", processed " << nLines << " lines" << std::endl;

   return EXIT_SUCCESS;
}

The Makefile很简单:

CFLAGS= -std=c++11 -O3 -march=native

all:    generate preprocess process

generate:   generate.cpp
        clang++ ${CFLAGS} generate.cpp -o generate

preprocess: preprocess.cpp
        clang++ ${CFLAGS} preprocess.cpp -o preprocess

process:    process.cpp
        clang++ ${CFLAGS} process.cpp -o process

当你运行它时,它会占用 CPU 2 分钟,如下所示:

time ./go
Starting job: 3
Starting job: 7
Starting job: 8
Starting job: 2
Starting job: 5
Starting job: 1
Starting job: 4
Starting job: 6
Ending job: 1, processed 5204 lines
Starting job: 9
Ending job: 2, processed 5203 lines
Ending job: 3, processed 5204 lines
Starting job: 11
Starting job: 10
Ending job: 4, processed 5204 lines
Starting job: 12
Ending job: 5, processed 5203 lines
Ending job: 6, processed 5203 lines
Starting job: 14
Starting job: 13
...
...
Starting job: 75
Ending job: 68, processed 5204 lines
Ending job: 69, processed 5203 lines
Starting job: 76
Starting job: 77
Ending job: 70, processed 5203 lines
Ending job: 71, processed 5204 lines
Ending job: 72, processed 5203 lines
Ending job: 77, processed 4535 lines
Ending job: 74, processed 5204 lines
Ending job: 73, processed 5205 lines
Ending job: 75, processed 5204 lines
Ending job: 76, processed 5203 lines

real    2m17.510s
user    16m24.533s
sys     0m4.426s

请注意,我没有执行任何显式 SIMD 或循环展开,也没有使用任何内在函数来形成点积。我怀疑您是否询问了有关形成点积的问题并将其标记为simd or avx,有人会帮你优化它。


另请注意,您可以轻松地在多台计算机上运行此代码GNU 并行,假设你有ssh登录他们,只需使用:

parallel -S host1,host2,host3 ....

例如,我的网络上有一台 6 核 Debian PC,因此我在 4 核 Mac 和 6 核 Debian 机器上并行运行上述代码:

parallel -S :,debian ...

然后需要 1 分 8 秒。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

两个大文件彼此的平行余弦相似度 的相关文章

  • 如何有效计算文档流中文档之间的相似度

    我收集文本文档 在 Node js 中 其中一个文档i表示为单词列表 考虑到新文档以文档流的形式出现 计算这些文档之间相似性的有效方法是什么 我目前对每个文档中单词的归一化频率使用余弦相似度 我不使用 TF IDF 词频 逆文档频率 因为我
  • 是否可以在GPU中实现Huffman解码?

    我们有一个用霍夫曼编码编码的数据库 这里的目的是将其及其关联的解码器复制到 GPU 上 然后在 GPU 上对数据库进行解码 并在解码后的数据库上执行操作 而无需将其复制回 CPU 上 我还远远不是霍夫曼专家 但我所知道的少数人表明 它似乎是
  • 使 CUDA 内存不足

    我正在尝试训练网络 但我明白了 我将批量大小设置为 300 并收到此错误 但即使我将其减少到 100 我仍然收到此错误 更令人沮丧的是 在 1200 个图像上运行 10 epoch 大约需要 40 分钟 有什么建议吗 错了 我怎样才能加快这
  • SPMD 与 Parfor

    我对 matlab 中的并行计算很陌生 我有一个创建分类器 SVM 的函数 我想用几个数据集来测试它 我有一个 2 核工作站 所以我想并行运行测试 有人可以向我解释一下以下之间的区别 dataset array dataset1 datas
  • TransactionScope() 和并行查询执行

    我们尝试在事务范围内运行并行查询以提高代码的性能 我们要在数据库中进行几项彼此没有连接的更改 我们可以这样运行代码 using var tran new System Transactions TransactionScope await
  • 如何将稀疏矩阵拆分为训练集和测试集?

    我想了解如何使用稀疏矩阵 我有这段代码可以生成多标签分类数据集作为稀疏矩阵 from sklearn datasets import make multilabel classification X y make multilabel cl
  • 使用监视器的单车道桥

    在大学里 我从 Gregory R Andrews Foundations of Multithreaded programming 中得到了这个规范的并行编程问题 虽然我有这本书的较新版本和俄语版本 但我发现了一个旧的英语变体并尝试正确传
  • 并行处理的ThreadPool和Pool

    有没有办法在 python 中同时使用 ThreadPool 和 Pool 来通过指定您希望使用的 CPU 和内核的数量来并行循环 例如 我将循环执行为 from multiprocessing dummy import Pool as T
  • Julia:如何让多个工作人员访问模块中的函数?

    我有以下测试模块 MyMod jl 来在 Julia 中存储一些测试函数 一些核心函数是串行编写的 其他函数并行调用核心函数 module MyMod export Dummy distribute data getfrom recombi
  • 分布式张量流中的并行进程

    我有带有训练参数的张量流神经网络 它是代理的 策略 网络正在核心程序的主张量流会话的训练循环中进行更新 在每个训练周期结束时 我需要将该网络传递给几个并行进程 工作人员 这些进程将使用它来从代理策略与环境的交互中收集样本 我需要并行执行 因
  • 带有 return 语句的 Julia @parallel for 循环

    如何在满足条件时立即返回所有工作人员的函数中编写并行 for 循环 IE 像这样的东西 function test n sync parallel for i in 1 1000 statement if condition return
  • iOS 上的 OpenCV - GPU 使用情况?

    我正在尝试开发一个 iOS 应用程序 可以对来自相机的视频执行实时效果 就像 iPad 上的 Photobooth 一样 我熟悉 OpenCV 的 API 但如果大多数处理是在 CPU 上完成而不是在 GPU 上完成 我担心 iOS 上的性
  • shell进程的并行执行

    有没有一个工具可以在 Windows 批处理文件中并行执行多个进程 我发现了一些有趣的 Linux 工具 parallel http mi eng cam ac uk er258 code parallel html and PPSS ht
  • OpenMP 动态调度与引导调度

    我正在研究 OpenMP 的调度 特别是不同的类型 我了解每种类型的一般行为 但澄清一下何时进行选择会很有帮助dynamic and guided调度 英特尔的文档 https software intel com en us articl
  • pyspark中的稀疏向量RDD

    我一直在使用 mllib 的功能通过 Python Pyspark 实现此处描述的 TF IDF 方法 https spark apache org docs 1 3 0 mllib feature extraction html http
  • python 线程是如何工作的?

    我想知道 python 线程是并发运行还是并行运行 例如 如果我有两个任务并在两个线程中运行它们 它们是同时运行还是计划同时运行 我知道GIL并且线程仅使用一个 CPU 核心 这是一个复杂的问题 需要大量解释 我将坚持使用 CPython
  • R 中使用 randomForest 进行内存高效预测

    TL DR我想知道使用基于大型数据集 数百个特征 数十万行 构建的随机森林模型执行批量预测的内存有效方法 Details 我正在处理一个大型数据集 内存中超过 3GB 并且想要使用以下方法进行简单的二进制分类randomForest 由于我
  • 处理异步并行任务的多个异常

    Problem 多个任务并行运行 所有任务 没有任务或其中任何任务都可能抛出异常 当所有任务完成后 必须报告所有可能发生的异常 通过日志 电子邮件 控制台输出 等等 预期行为 我可以通过 linq 使用异步 lambda 构建所有任务 然后
  • 如何在 Emgu CV 项目中利用 OpenCL

    我是使用 Emgu CV 的新手 并开始创建小型示例项目 例如面部检测 眼睛检测等 如果我可以利用 OpenCL 来加速使用 GPU 的过程 那就太好了 否则 当我降低scaleFactor时 它会导致大量的CPU利用率 我怎样才能做到这一
  • Parallel.For 和 Break() 误解?

    我正在研究 For 循环中的并行性中断 看完之后this http tipsandtricks runicsoft com CSharp ParallelClass html and this http reedcopsey com 201

随机推荐

  • 之间的区别:在 Intellij IDEA 中构建和制作

    对于Intellij IDEA中的JAVA EE项目 有什么区别 重建项目并创建项目 在菜单 构建 中 谢谢 您可以参考https www jetbrains com help idea 2016 2 compilation types h
  • MySql - Sequelize - 无法添加外键约束

    我正在尝试使用 Nodejs Sequelize 创建数据库 被调用的命令是 CREATE TABLE IF NOT EXISTS wheel id INTEGER NOT NULL auto increment createdAt DAT
  • Silverlight 绑定到布尔属性值的逆

    我想将控件可见性绑定到布尔属性值的倒数 我有一个属性 CanDownload 如果它是 true 那么我想隐藏文本框 反之亦然 我怎样才能实现这个目标 Thanks 被问到这样的问题so经常和答案so类似我认为是时候对所有 好吧可能是 大多
  • 根据两个条件对多个表进行排序的宏

    我徒劳地尝试让下面的宏正确运行 最终目标是一个宏 它将根据两个条件对多个表 在单个工作表上 进行排序 并且也适用于任何活动的工作表 我可以使用精确的表引用创建一个宏 但寻求更灵活的方法以避免每个工作表都有一个宏 我的大部分代码来自 Doug
  • 如何使用 VBA 将 & 符号从 Excel 文件写入 XML 文件?

    首先 对于 VBA 来说 我是一个完全的新手 但不幸的是我被抛弃了这段代码 我必须处理它 该应用程序的作用是复制 Excel xlsm 文件中的信息并将其粘贴到 XML 文件中以供进一步处理 问题是 一切都进行得很顺利 直到我在 Excel
  • 关于 Angular 中的位置更改

    有没有办法检测 AngularJS 中的全局位置变化 而不仅仅是单个控制器 我的目标是检测每个位置变化 或者有什么有效的方法来观察 window location href 的变化 routeChangeSuccess 据我了解仅适用于单个
  • ByteBuffer.wrap(byte[]) 会导致长时间运行的应用程序内存泄漏吗?

    我试图在网上搜索 但没有找到答案 基于java doc http docs oracle com javase 7 docs api java nio ByteBuffer html wrap byte 5B 5D ByteBuffer w
  • HasResolution 类型类

    我刚刚查了一下HasResolution 类型类 https hackage haskell org package base 4 10 1 0 docs Data Fixed html t HasResolution它有一个单一的方法 r
  • 为什么 .NET 中的多维数组比普通数组慢?

    Edit 我向大家道歉 当我实际上想说 多维数组 时 我使用了术语 锯齿状数组 如下面的示例所示 对于使用了错误的名字 我深表歉意 我实际上发现锯齿状数组比多维数组更快 我已经添加了锯齿状阵列的测量值 I was trying to use
  • 带棱镜的 AutoWirePartialView 不起作用或使用不当?

    我正在尝试使用棱镜7 1AutoWirePartialView绑定一个PartialView到它的 viewModel 但是 绑定不起作用 或者至少将 viewModel 设置为PartialView似乎不起作用 它仍然具有页面的 Bind
  • 当用户编辑字段中的值时,自定义 DatePicker 作为首选项不会保留值

    我创建了一个 DatePickerPreference 即我扩展了 DialogPreference 并在内部创建了一个 DatePicker 对象 并且让它几乎完美地工作 当您单击向上和向下箭头时 它会更改值并保存您选择的值 但是 如果您
  • OpenGL/GLUT 中的鼠标拖动对象[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我一整天都在寻找简单程序的教程或示例代码 单击对象 例如 2D 矩形 然后当您按住并移动鼠标时 对象会跟随鼠标 然后释放鼠标时 对象仍保留
  • 如何在运行时更改语言而不会出现布局问题

    我有一个 winforms 应用程序 用户必须能够在运行时更改语言 为了概括该开关并避免必须对控件名称进行硬编码 我尝试了以下扩展 internal static void SetLanguage this Form form Cultur
  • 如何在 Windows 10 C# 通用应用程序中使用 C++ 类? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我想在 Windows 10 C 通用应用程序中执行 cpp 类的方法 由于我是 Windows 应用程序开发和 C 的新手 所以我可
  • 如何使用cmake在android studio中添加外部库?

    我正在尝试使用 cMake 将 live555 so 和 h 文件与 Android 项目链接 如果我不使用绝对路径 则会出现错误 My cMake file cmake minimum required VERSION 3 4 1 inc
  • 使用 jQuery Sortable() 选择多个项目?

    我需要在 jquery 可排序容器中同时拖动多个项目 在本例中 它是应用了 sortable 行为的父 div 内的一系列嵌套 div 有什么建议么 如果您询问是否可以选择多个项目 例如在一个实例中选择 1 3 和 7 在另一个实例中选择
  • 在Django通道中执行数据库查询

    我正在尝试创建一个非常简单的系统 用户为了使用消费者 需要在 WS url 中输入密钥 例如 ws 127 0 0 1 8000 main key KEY 一旦消费者被调用 Django Channels 需要执行一个非常简单的数据库查询来
  • Objective C:如何通过程序从一个选项卡栏切换到另一个选项卡栏

    我的标签栏控制器中有 5 个不同的标签 我的目的是能够通过代码从一个选项卡栏进行切换 例如 我当前位于应用程序的第五个选项卡中 当我单击 完成 按钮时 应用程序应将我的视图切换到属于第一个选项卡的 rootview 控制器 关于我如何做到这
  • SlickGrid 中的额外列

    即使没有垂直滚动条 SlickGrid 始终在标题的最右侧保留一点空间 这个额外的空间看起来就像一个额外的列 我不想要这个额外的空间 我没有找到 SlickGrid 组件的任何公开 API 来删除它 我在里面看到过自动调整列大小 Slick
  • 两个大文件彼此的平行余弦相似度

    我有两个文件 A 和 B A has 400 000 lines each having 50 float values B has 40 000 lines having 50 float values 对于 B 中的每一行 我需要在 A