@@ -107,6 +107,51 @@ static size_t type_to_elemsize(int type)
107107 return 0 ; // null
108108}
109109
110+ static std::string python_string_literal (const std::string& s)
111+ {
112+ std::string r = " '" ;
113+ for (char ch : s)
114+ {
115+ if (ch == ' \\ ' || ch == ' \' ' )
116+ {
117+ r += ' \\ ' ;
118+ r += ch;
119+ }
120+ else if (ch == ' \n ' )
121+ {
122+ r += " \\ n" ;
123+ }
124+ else if (ch == ' \r ' )
125+ {
126+ r += " \\ r" ;
127+ }
128+ else if (ch == ' \t ' )
129+ {
130+ r += " \\ t" ;
131+ }
132+ else
133+ {
134+ r += ch;
135+ }
136+ }
137+ r += " '" ;
138+ return r;
139+ }
140+
141+ static void write_python_load_input_helper (FILE * pyfp)
142+ {
143+ fprintf (pyfp, " \n " );
144+ fprintf (pyfp, " def _pnnx_load_input(path):\n " );
145+ fprintf (pyfp, " arr = np.load(path)\n " );
146+ fprintf (pyfp, " if arr.dtype.byteorder not in ('=', '|'):\n " );
147+ fprintf (pyfp, " native = '<' if np.little_endian else '>'\n " );
148+ fprintf (pyfp, " if arr.dtype.byteorder != native:\n " );
149+ fprintf (pyfp, " arr = arr.byteswap().view(arr.dtype.newbyteorder('='))\n " );
150+ fprintf (pyfp, " if not arr.flags.c_contiguous:\n " );
151+ fprintf (pyfp, " arr = np.ascontiguousarray(arr)\n " );
152+ fprintf (pyfp, " return torch.from_numpy(arr)\n " );
153+ }
154+
110155static int string_to_type (const char * s)
111156{
112157 if (strcmp (s, " f32" ) == 0 ) return 1 ;
@@ -1456,7 +1501,7 @@ static std::string make_index_expression(const Operator* op)
14561501 return index_expr;
14571502}
14581503
1459- int Graph::python (const std::string& pypath, const std::string& pnnxbinpath, const std::vector<std::vector<int64_t > >& input_shapes)
1504+ int Graph::python (const std::string& pypath, const std::string& pnnxbinpath, const std::vector<std::vector<int64_t > >& input_shapes, const std::vector<std::string>& input_npy_paths )
14601505{
14611506 FILE * pyfp = fopen (pypath.c_str (), " wb" );
14621507 if (!pyfp)
@@ -1477,6 +1522,9 @@ int Graph::python(const std::string& pypath, const std::string& pnnxbinpath, con
14771522 fprintf (pyfp, " except:\n " );
14781523 fprintf (pyfp, " pass\n " );
14791524
1525+ if (!input_npy_paths.empty ())
1526+ write_python_load_input_helper (pyfp);
1527+
14801528 fprintf (pyfp, " \n " );
14811529
14821530 fprintf (pyfp, " class Model(nn.Module):\n " );
@@ -2771,6 +2819,7 @@ int Graph::python(const std::string& pypath, const std::string& pnnxbinpath, con
27712819 fprintf (pyfp, " torch.manual_seed(0)\n " );
27722820
27732821 int input_shapes_i = 0 ;
2822+ int input_npy_i = 0 ;
27742823
27752824 std::vector<std::string> input_names;
27762825 for (const Operator* op : ops)
@@ -2779,6 +2828,18 @@ int Graph::python(const std::string& pypath, const std::string& pnnxbinpath, con
27792828 continue ;
27802829
27812830 const Operand* r = op->outputs [0 ];
2831+ std::string input_name = std::string (" v_" ) + sanitize_identifier (r->name );
2832+
2833+ if (input_npy_i < (int )input_npy_paths.size ())
2834+ {
2835+ std::string path_literal = python_string_literal (input_npy_paths[input_npy_i]);
2836+ fprintf (pyfp, " %s = _pnnx_load_input(%s)\n " , input_name.c_str (), path_literal.c_str ());
2837+ input_names.push_back (input_name);
2838+ input_npy_i++;
2839+ if (!input_shapes.empty ())
2840+ input_shapes_i++;
2841+ continue ;
2842+ }
27822843
27832844 std::vector<int > input_shape;
27842845 if (input_shapes.empty ())
@@ -2794,7 +2855,6 @@ int Graph::python(const std::string& pypath, const std::string& pnnxbinpath, con
27942855 }
27952856 }
27962857
2797- std::string input_name = std::string (" v_" ) + sanitize_identifier (r->name );
27982858 if (type_is_integer (r->type ))
27992859 {
28002860 fprintf (pyfp, " %s = torch.randint(10, (" , input_name.c_str ());
0 commit comments