首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >PythontoC++通信失败

PythontoC++通信失败
EN

Stack Overflow用户
提问于 2021-10-28 17:31:25
回答 2查看 142关注 0票数 1

我在python中有4个numpy数组。我将它们发送到一个派生的c++进程中。这适用于小数组,但是当数组变得太大时,c++程序会读取一个不正确的值(看起来与机器(小)相反的字节顺序)。

python/numpy数组的典型值是0.25、0.5、0.7等。

c++程序将正确地接收这些值,直到得到数千个元素,然后c++程序开始接收奇怪的值,这些值似乎是它应该得到的小endian值的大端版本。它与同步无关,因为中间数组完美地发送所有数据,不管大小如何。这只是我的第一个也是最后一个数组,尽管所有python/numpy数组都被迫是相同的类型。

一旦数组变得太大: c++接收的值如下:-4.34345e-266,-5.67456e-50,等等。

有谁能猜到为什么会发生这种事?我被困在这上面已经有一段时间了。

编辑:这似乎是一个平台问题。这些代码在我的本地计算机(Ubuntu18.04,python3.6.9,g++ 7.5.0)上工作,但在Amazon (Ubuntu18.04,python3.6.9,g++ 7.5.0)上失败--似乎是相同的规格。我是否应该考虑其他平台依赖关系?

编辑2:我已经缩小了范围。这似乎是一个一旦过了一定时间就会发生的问题,而不是在某个数组大小之后发生的问题。这就是为什么我的本地机器在问题出现之前传输所有数据的原因。AWS使用vCPU (虚拟),在进程之间通信可能需要更长的时间,这就是为什么我注意到它在云服务器而不是本地服务器上.任何可能导致这种情况的建议都是有帮助的。

代码语言:javascript
复制
# python

...

p = subprocess.Popen(
    'shell text to launch C++ process',
    shell=True, 
    stdin=subprocess.PIPE,
    stdout=subprocess.PIPE,
    stderr=subprocess.PIPE,
)

...

<loop through all arrays>
   array = arrays[i]
   
   p.stdin.write(<the size and type of array>)

   <looping through numpy array>
      value = array[x][y]
      b = struct.pack('<d', value)
      p.stdin.write(b)
   p.stdin.flush()
代码语言:javascript
复制
// c++

...

<loop through expected arrays>
    
    int size;
    r = fread(&size, sizeof(int), 1, stdin);

    <allocate array with size and type>

    <loop through size of array>
        double value;
        r = fread(&value, sizeof(double), 1, stdin);
        
        <input values into allocated array>

下面是发送之前的python中的唯一值,以及在接收后的c++中的唯一值(aid是数组的id):

代码语言:javascript
复制
py >> aid:  0  val :  1.5147748861987186e-07
py >> aid:  0  val :  0.00027064327098285035
py >> aid:  0  val :  0.00032440267655912817
py >> aid:  0  val :  0.00039440984799195717
py >> aid:  0  val :  0.00048666128622491974
py >> aid:  0  val :  0.0006088895533821487
py >> aid:  0  val :  0.0007693269194044289
py >> aid:  0  val :  0.0009713703111738414
py >> aid:  0  val :  0.0011995490513889394
py >> aid:  0  val :  0.0013989766453051436
py >> aid:  0  val :  0.0014816246426333445
py >> aid:  0  val :  0.000971370311173842
py >> aid:  0  val :  0.000608889553382149
py >> aid:  0  val :  0.0003944098479919573
py >> aid:  0  val :  0.0003244026765591282
py >> aid:  0  val :  0.0006091367065721885
py >> aid:  0  val :  1.1195904948938864
py >> aid:  0  val :  0.0006535893828657839
py >> aid:  0  val :  0.0006896927523924802
py >> aid:  0  val :  0.0007134077346636406
py >> aid:  0  val :  0.0007216922125962245
py >> aid:  0  val :  0.17
py >> aid:  0  val :  205.0
py >> aid:  0  val :  0.0016111429295754896
py >> aid:  0  val :  0.001897252365911768
py >> aid:  0  val :  0.0020511342434220143
py >> aid:  0  val :  0.0021170160163027038
py >> aid:  0  val :  0.0021201443585756935
py >> aid:  0  val :  2.407359807268656e-06
py >> aid:  0  val :  0.0011768390663802282
py >> aid:  0  val :  0.0013958354194843637
py >> aid:  0  val :  0.001670834944478645
py >> aid:  0  val :  0.002016004763800768
py >> aid:  0  val :  0.002444680031953682
py >> aid:  0  val :  0.0029617508597233667
py >> aid:  0  val :  0.0035475199335043986
py >> aid:  0  val :  0.004133617431826363
py >> aid:  0  val :  0.0045900107907456715
py >> aid:  0  val :  0.0047657186623283965
py >> aid:  0  val :  0.004133617431826364
py >> aid:  0  val :  0.0035475199335044
py >> aid:  0  val :  0.0024446800319536835
py >> aid:  0  val :  0.0016708349444786454
py >> aid:  1  val :  0.0
py >> aid:  1  val :  0.1978674776035768
py >> aid:  2  val :  295.15

c++ >> aid: 0 val: 1.51477e-07
c++ >> aid: 0 val: 0.000270643
c++ >> aid: 0 val: 0.000324403
c++ >> aid: 0 val: 0.00039441
c++ >> aid: 0 val: 0.000486661
c++ >> aid: 0 val: 0.00060889
c++ >> aid: 0 val: 0.000769327
c++ >> aid: 0 val: 0.00097137
c++ >> aid: 0 val: 0.00119955
c++ >> aid: 0 val: 0.00139898
c++ >> aid: 0 val: 0.00148162
c++ >> aid: 0 val: 0.00097137
c++ >> aid: 0 val: 0.00060889
c++ >> aid: 0 val: 0.00039441
c++ >> aid: 0 val: 0.000324403
c++ >> aid: 0 val: 0.000609137
c++ >> aid: 0 val: 1.11959
c++ >> aid: 0 val: 0.000653589
c++ >> aid: 0 val: 0.000689693
c++ >> aid: 0 val: 0.000713408
c++ >> aid: 0 val: 0.000721692
c++ >> aid: 0 val: 0.17
c++ >> aid: 0 val: 205
c++ >> aid: 0 val: -7.26344e+201
c++ >> aid: 0 val: -7.26344e+201
c++ >> aid: 0 val: -1.11628e-125
c++ >> aid: 0 val: -1.11628e-125
c++ >> aid: 0 val: -7.26344e+201
c++ >> aid: 0 val: -4.31009e+12
c++ >> aid: 0 val: -1.49167e-154
c++ >> aid: 0 val: -1.49167e-154
c++ >> aid: 0 val: -4.31009e+12
c++ >> aid: 0 val: -7.26344e+201
c++ >> aid: 0 val: -4.31009e+12
c++ >> aid: 0 val: 3.27272e+181
c++ >> aid: 0 val: -7.26344e+201
c++ >> aid: 0 val: 3.27272e+181
c++ >> aid: 0 val: 3.27272e+181
c++ >> aid: 0 val: 2.31398e-204
c++ >> aid: 0 val: -7.26344e+201
c++ >> aid: 0 val: 2.31398e-204
c++ >> aid: 0 val: 2.31398e-204
c++ >> aid: 0 val: -3.46371e+65
c++ >> aid: 0 val: -7.26344e+201
c++ >> aid: 0 val: -3.46371e+65
c++ >> aid: 0 val: -3.46371e+65
c++ >> aid: 0 val: 3.12744e+114
c++ >> aid: 0 val: -7.26344e+201
c++ >> aid: 0 val: 3.12744e+114
c++ >> aid: 0 val: 3.12744e+114
c++ >> aid: 0 val: 1.23842e+146
c++ >> aid: 0 val: 1.23842e+146
c++ >> aid: 0 val: 5.81017e-69
c++ >> aid: 0 val: 9.07095e+38
c++ >> aid: 0 val: 9.07095e+38
c++ >> aid: 0 val: -3.08372e+147
c++ >> aid: 0 val: -3.08372e+147
c++ >> aid: 0 val: 2.46041e+154
c++ >> aid: 0 val: 2.46041e+154
c++ >> aid: 0 val: -4.86069e-290
c++ >> aid: 0 val: -4.86069e-290
c++ >> aid: 0 val: 1.33577e-275
c++ >> aid: 0 val: 1.33577e-275
c++ >> aid: 0 val: 8.41193e+15
c++ >> aid: 0 val: 8.41193e+15
c++ >> aid: 0 val: 4.09165e-233
c++ >> aid: 0 val: 4.09165e-233
c++ >> aid: 0 val: -7.36835e+223
c++ >> aid: 0 val: -7.36835e+223
c++ >> aid: 0 val: -6.59221e+62
c++ >> aid: 0 val: -6.59221e+62
c++ >> aid: 0 val: -1.60471e-283
c++ >> aid: 0 val: -1.60471e-283
c++ >> aid: 0 val: -6.59221e+62
c++ >> aid: 0 val: -7.36835e+223
c++ >> aid: 0 val: -7.36835e+223
c++ >> aid: 0 val: 4.09165e-233
c++ >> aid: 0 val: 4.09165e-233
c++ >> aid: 0 val: 8.41193e+15
c++ >> aid: 0 val: 1.33577e-275
c++ >> aid: 0 val: 1.33577e-275
c++ >> aid: 0 val: -4.86069e-290
c++ >> aid: 0 val: 2.46041e+154
c++ >> aid: 0 val: 2.46041e+154
c++ >> aid: 0 val: -3.08372e+147
c++ >> aid: 0 val: 9.07095e+38
c++ >> aid: 0 val: 5.81017e-69
c++ >> aid: 1 val: 0
c++ >> aid: 1 val: 0.197867
c++ >> aid: 2 val: 295.15

这是一个正在发生的事情的样本。运行python代码,看看它是如何通信的。在创建此示例时,我注意到对dim的限制是144,这意味着我的计算机可以传输的最大字节在失败之前是165888。(编辑:这是由于管道阻塞时,读和写是在同一个线程,如下面的答案指出,但我的实际代码使用线程和非阻塞。这个问题似乎仍然与时间间隔有关,因为它在我的本地服务器上工作)

代码语言:javascript
复制
# python 3

import numpy
import subprocess
import struct
import sys
import time

s = subprocess.Popen(
    'g++ -Ofast -pthread -o script comm_test.cpp && ./script',
    shell=True, 
    stdin=subprocess.PIPE,
    stdout=subprocess.PIPE,
    stderr=subprocess.PIPE,
    bufsize=-1,
)

dim = 4
a = numpy.arange(dim*dim, dtype=numpy.float64).reshape((dim, dim))
print(a)
bdim = dim.to_bytes(4, byteorder=sys.byteorder)
s.stdin.write(bdim)
for i in range(dim):
    for j in range(dim):
        b = struct.pack('<d', a[i][j])
        s.stdin.write(b)
s.stdin.flush()
while True:
    data = s.stderr.readline()
    text = '[c++] {}'.format(data.decode('utf-8'), end='')
    print(text)
    if 'done' in text:
        break
代码语言:javascript
复制
// comm_test.cpp

#include <iostream>
#include <stdio.h>
#include <streambuf>
using namespace std;

int main(){
    cerr << "started" << endl;
    int r, dim;
    r = fread(&dim, sizeof(int), 1, stdin);
    cerr << "dim: " << dim << endl;
    double* array = new double[dim*dim];
    for(int i = 0; i < dim*dim; i++){
        double val;
        r = fread(&val, sizeof(double), 1, stdin);
        array[i] = val;
        cerr << val << endl;
    }
    cerr << "done" << endl;
    return 0;
}
EN

回答 2

Stack Overflow用户

发布于 2021-10-28 23:02:45

您的问题不是Python方面的。您的问题是C应用程序正在填充它的stdout管道缓冲区和阻塞,因为您的Python代码在完成编写之前不会读取任何内容。

要进行这种交流,需要读写同时进行。您可以使用一个简单的TCP套接字来完成这个任务,但是您也会遇到同样的问题;缓冲区不是无限大的。

票数 0
EN

Stack Overflow用户

发布于 2021-10-29 15:12:41

我想通了。我在某个地方有一个循环,它在定时器上敲击c++进程。它是在所有初始数据传输完成之前运行的,因此ping会在传输过程中的某个位置发送几字节数据(因此我无法确定一个确切的错误点),这将抛出所有后续的数据片段。我正确地假设我的本地计算机IPC比更快。这就是为什么我的本地计算机工作-最初的数据传输能够超过速度的定时器循环.

由于这不会对任何人有多大帮助,所以我可以发布一个更好版本的简单进程间管道通信(使用线程,因此它对传输的数据没有任何限制):

代码语言:javascript
复制
# python 3

import numpy
import subprocess
import struct
import sys
import time
import threading
from time import perf_counter

s = subprocess.Popen(
    'g++ -Ofast -pthread -o script comm_test.cpp && ./script',
    shell=True, 
    stdin=subprocess.PIPE,
    stdout=subprocess.PIPE,
    stderr=subprocess.STDOUT,
)

def reader(s):
    while True:
        data = s.stdout.readline()
        text = '[c++] {}'.format(data.decode('utf-8'), end='')
        print(text)
        if 'done' in text:
            break

r = threading.Thread(target=reader, args=(s,))
r.start()
dim = 1000
a = numpy.arange(dim*dim, dtype=numpy.float64).reshape((dim, dim))
print(a)
bdim = struct.pack('<i', dim)
s.stdin.write(bdim)
t1 = perf_counter()
for i in range(dim):
    for j in range(dim):
        val = a[i][j]
        val = numpy.float64(val)
        b = struct.pack('<d', val)
        s.stdin.write(b)
s.stdin.flush()
t2 = perf_counter()
r.join()
print('finished in {:.4f} seconds'.format(t2-t1))
代码语言:javascript
复制
// c++ comm_test.cpp

#include <iostream>
#include <stdio.h>
#include <streambuf>

using namespace std;

int main(){
    cerr << "started" << endl;
    int r, dim;
    r = fread(&dim, sizeof(int), 1, stdin);
    cerr << "dim: " << dim << endl;
    double* array = new double[dim*dim];
    for(int i = 0; i < dim*dim; i++){
        double val;
        r = fread(&val, sizeof(double), 1, stdin);
        array[i] = val;
        cerr << val << endl;
    }
    cerr << "done" << endl;
    return 0;
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69758580

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档